From 8d1042c689a043fb0622aae84f8a36acc4bc0b46 Mon Sep 17 00:00:00 2001 From: "T. Schreiber" Date: Tue, 12 Nov 2019 10:05:37 +0000 Subject: [PATCH 01/73] initial nat gateway branche --- otcextensions/sdk/__init__.py | 38 ++---- otcextensions/sdk/nat/v2/_proxy.py | 160 ++---------------------- otcextensions/sdk/nat/v2/nat_gateway.py | 54 ++++++++ 3 files changed, 74 insertions(+), 178 deletions(-) create mode 100644 otcextensions/sdk/nat/v2/nat_gateway.py diff --git a/otcextensions/sdk/__init__.py b/otcextensions/sdk/__init__.py index f9837b5b8..ec60383f8 100644 --- a/otcextensions/sdk/__init__.py +++ b/otcextensions/sdk/__init__.py @@ -12,13 +12,9 @@ import importlib import os -import openstack from openstack import _log from openstack import utils -from otcextensions.sdk.compute.v2 import server -from otcextensions.common import exc - _logger = _log.setup_logging('openstack') @@ -114,7 +110,8 @@ 'service_type': 'mrs' }, 'nat': { - 'service_type': 'nat' + 'service_type': 'nat', + 'append_project_id': True, }, 'obs': { 'service_type': 'obs', @@ -243,15 +240,6 @@ def get_ak_sk(conn): return(ak, sk) -def patch_openstack_resources(): - openstack.compute.v2.server.Server._get_tag_struct = \ - server.Server._get_tag_struct - openstack.compute.v2.server.Server.add_tag = server.Server.add_tag - openstack.compute.v2.server.Server.remove_tag = server.Server.remove_tag - openstack.exceptions.raise_from_response = \ - exc.raise_from_response - - def load(conn, **kwargs): """Register supported OTC services and make them known to the OpenStackSDK @@ -271,6 +259,7 @@ def load(conn, **kwargs): if service['service_type'] in conn._proxies: del conn._proxies[service['service_type']] # attr = getattr(conn, service_name) + # print(hasattr(conn, service_name)) # delattr(conn, service['service_type']) sd = _get_descriptor(service_name) @@ -284,18 +273,15 @@ def load(conn, **kwargs): if ep and not ep.rstrip('/').endswith('\\%(project_id)s') \ and not ep.rstrip('/').endswith('$(tenant_id)s') \ and not ep.rstrip('/').endswith(project_id): - key = '_'.join([ - sd.service_type.lower().replace('-', '_'), - 'endpoint_override']) - if key not in conn.config.config: - conn.config.config[key] = utils.urljoin(ep, - '%(project_id)s') - + conn.config.config[ + '_'.join([ + sd.service_type.lower().replace('-', '_'), + 'endpoint_override' + ]) + ] = utils.urljoin(ep, '%(project_id)s') elif service.get('set_endpoint_override', False): - # SDK respects skip_discovery only if endpoint_override is set. - # In case, when append_project_id is skipped for the service, - # but the discovery on the service is not working - we might be - # failing dramatically. + # We need to set endpoint_override for OBS, since otherwise it + # fails dramatically ep = conn.endpoint_for(sd.service_type) conn.config.config[ '_'.join([ @@ -308,8 +294,6 @@ def load(conn, **kwargs): # for some proxies to use them setattr(conn, 'get_ak_sk', get_ak_sk) - patch_openstack_resources() - return None diff --git a/otcextensions/sdk/nat/v2/_proxy.py b/otcextensions/sdk/nat/v2/_proxy.py index 4df1a1a06..f7ace7ca1 100644 --- a/otcextensions/sdk/nat/v2/_proxy.py +++ b/otcextensions/sdk/nat/v2/_proxy.py @@ -9,170 +9,28 @@ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. -from otcextensions.sdk.nat.v2 import gateway as _gateway -from otcextensions.sdk.nat.v2 import snat as _snat -from otcextensions.sdk.nat.v2 import dnat as _dnat +from otcextensions.sdk.nat.v2 import nat_gateway as _nat_gateway from openstack import proxy class Proxy(proxy.Proxy): - skip_discovery = True + def gateways(self, **attrs): + return self._list(_nat_gateway.NatGateway, **attrs) - # ======== Gateway ======== def create_gateway(self, **attrs): """Create a new gateway from attributes :param dict attrs: Keyword arguments which will be used to create - a :class:`~otcextensions.sdk.nat.v2.gateway.Gateway` + a :class:`~otcextensions.sdk.nat.v2.nat_gateway.NatGateway """ - return self._create(_gateway.Gateway, **attrs) + return self._create(_nat_gateway.NatGateway, **attrs) - def delete_gateway(self, gateway, ignore_missing=True): - """Delete a gateway - - :param gateway: key id or an instance of - :class:`~otcextensions.sdk.nat.v2.gateway.Gateway` - :param bool ignore_missing: When set to ``False`` - :class:`~openstack.exceptions.ResourceNotFound` will be raised when - the gateway does not exist. - When set to ``True``, no exception will be set when attempting to - delete a nonexistent gateway. - - :returns: Gateway been deleted - :rtype: :class:`~otcextensions.sdk.nat.v2.gateway.Gateway` - """ - return self._delete(_gateway.Gateway, gateway, - ignore_missing=ignore_missing) - - def gateways(self, **query): - """Return a generator of gateways - - :param dict query: Optional query parameters to be sent to limit - the resources being returned. - :returns: A generator of gateway objects - :rtype: :class:`~otcextensions.sdk.nat.v2.gateway.Gateway` - """ - return self._list(_gateway.Gateway, **query) - - def get_gateway(self, gateway): - """Get a single gateway - - :param gateway: The value can be the ID of a NAT Gatway or a - :class:`~otcextensions.sdk.nat.v2.gateway.Gateway` - instance. - - :returns: One :class:`~otcextensions.sdk.nat.v2.gateway.Gateway` - :raises: :class:`~openstack.exceptions.ResourceNotFound` - when no resource can be found. - """ - return self._get(_gateway.Gateway, gateway) - - def update_gateway(self, gateway, **attrs): - """Update a gateway - - :param gateway: Either the ID of a gateway or a - :class:`~otcextensions.sdk.nat.v2.gateway.Gateway` - instance. - :param dict attrs: The attributes to update on the gateway represented - by ``gateway``. - - :returns: The updated gateway - :rtype: :class:`~otcextensions.sdk.nat.v2.gateway.Gateway` - """ - return self._update(_gateway.Gateway, gateway, **attrs) - - # ======== SNAT rules ======== - def create_snat_rule(self, **attrs): - """Create a new SNAT rule from attributes - - :param dict attrs: Keyword arguments which will be used to create - a :class:`~otcextensions.sdk.nat.v2.snat.Snat` - """ - return self._create(_snat.Snat, **attrs) - - def delete_snat_rule(self, snat, ignore_missing=True): - """Delete a SNAT rule - - :param bool ignore_missing: When set to ``False`` - :class:`~openstack.exceptions.ResourceNotFound` will be raised when - the SNAT rule does not exist. - When set to ``True``, no exception will be set when attempting to - delete a nonexistent SNAT rule. - - :returns: SNAT rule been deleted - :rtype: :class:`~otcextensions.sdk.nat.v2.snat.Snat` - """ - return self._delete(_snat.Snat, snat, ignore_missing=ignore_missing) - - def get_snat_rule(self, snat_rule): - """Get a single SNAT rule - - :param snat_rule: The value can be the ID of a SNAT rule or a - :class:`~otcextensions.sdk.nat.v2.snat.Snat` - instance. - - :returns: One :class:`~otcextensions.sdk.nat.v2.snat.Snat` - :raises: :class:`~openstack.exceptions.ResourceNotFound` - when no resource can be found. - """ - return self._get(_snat.Snat, snat_rule) - - def snat_rules(self, **query): - """Return a generator of SNAT rules - - :param dict query: Optional query parameters to be sent to limit - the resources being returned. - :returns: A generator of Snat rule objects - :rtype: :class:`~otcextensions.sdk.nat.v2.snat.Snat` - """ - return self._list(_snat.Snat, **query) - - # ======== DNAT rules ======== - def create_dnat_rule(self, **attrs): - """Create a new DNAT rule from attributes + def delete_gateway(self, id): + """Create a new gateway from attributes :param dict attrs: Keyword arguments which will be used to create - a :class:`~otcextensions.sdk.nat.v2.dnat.Dnat` - """ - return self._create(_dnat.Dnat, **attrs) - - def delete_dnat_rule(self, dnat, ignore_missing=True): - """Delete a DNAT rule - - :param dict attrs: Keyword arguments which will be used to delete - a :class:`~otcextensions.sdk.nat.v2.dnat.Dnat` - :param bool ignore_missing: When set to ``False`` - :class:`~openstack.exceptions.ResourceNotFound` will be raised when - the DNAT rule does not exist. - When set to ``True``, no exception will be set when attempting to - delete a nonexistent DNAT rule. - - :returns: DNAT rule been deleted - :rtype: :class:`~otcextensions.sdk.nat.v2.dnat.Dnat` - """ - return self._delete(_dnat.Dnat, dnat, ignore_missing=ignore_missing) - - def get_dnat_rule(self, dnat_rule): - """Get a single DNAT rule - - :param dnat_rule: The value can be the ID of a DNAT rule or a - :class:`~otcextensions.sdk.nat.v2.dnat.Dnat` - instance. - - :returns: One :class:`~otcextensions.sdk.nat.v2.dnat.Dnat` - :raises: :class:`~openstack.exceptions.ResourceNotFound` - when no resource can be found. - """ - return self._get(_dnat.Dnat, dnat_rule) - - def dnat_rules(self, **query): - """Return a generator of DNAT rules - - :param dict query: Optional query parameters to be sent to limit - the resources being returned. - :returns: A generator of DNAT rules objects - :rtype: :class:`~otcextensions.sdk.nat.v2.dnat.Dnat` + a :class:`~otcextensions.sdk.nat.v2.nat_gateway.NatGateway """ - return self._list(_dnat.Dnat, **query) + return self._delete(_nat_gateway.NatGateway, id=id) diff --git a/otcextensions/sdk/nat/v2/nat_gateway.py b/otcextensions/sdk/nat/v2/nat_gateway.py new file mode 100644 index 000000000..d87da1924 --- /dev/null +++ b/otcextensions/sdk/nat/v2/nat_gateway.py @@ -0,0 +1,54 @@ +# 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. +from openstack import resource + +class NatGateway(resource.Resource): + resources_key = 'nat_gateways' + base_path = '/nat_gateways' + + # capabilities + allow_create = True + allow_delete = True + allow_list = True + #allow_get = True + + # Properties + #: Specifies the ID of the NAT gateway. + id = resource.Body('id') + #: Specifies the project ID + tenant_id = resource.Body('tenant_id') + #: Specifies the name of the NAT gateway. + #: Contains only digits, letters, underscores and hyphens + name = resource.Body('name') + #: Provides description of NAT Gateway + description = resource.Body('description') + #: Specifies the type of the NAT gateway. + #: *1:* small type, supports up to 10,000 SNAT connections + #: *2:* medium type, supports up to 50,000 SNAT connections + #: *3:* large type, supports up to 200,000 SNAT connections + #: *4:* extra-large type, supports up to 1,000,000 SNAT connections + spec = resource.Body('spec', type=int) + #: Specifies the router ID + router_id = resource.Body('router_id') + #: Specifies the network ID of the downstream interface + internal_network_id = resource.Body('internal_network_id') + #: Specifies the status + status = resource.Body('status') + #: Specifies whether GW is up or down + #: *true:* Gw is up + #: *false:* GW is down + admin_state_up = resource.Body('admin_state_up', type=bool) + #: Specifies when GW was is created + #: format is *yyyy-mm-dd hh:mm:ss* + created_at = resource.Body('created_at') + + From 619f3dc24dab413406326813ca243540d4afdda6 Mon Sep 17 00:00:00 2001 From: "T. Schreiber" Date: Tue, 12 Nov 2019 14:03:38 +0000 Subject: [PATCH 02/73] added snat and dnat resource --- otcextensions/sdk/nat/v2/_proxy.py | 44 +++++++++++++++--- otcextensions/sdk/nat/v2/dnat.py | 60 ++++++++++--------------- otcextensions/sdk/nat/v2/nat_gateway.py | 5 ++- otcextensions/sdk/nat/v2/snat.py | 52 +++++++++------------ 4 files changed, 88 insertions(+), 73 deletions(-) diff --git a/otcextensions/sdk/nat/v2/_proxy.py b/otcextensions/sdk/nat/v2/_proxy.py index f7ace7ca1..36cd1f64e 100644 --- a/otcextensions/sdk/nat/v2/_proxy.py +++ b/otcextensions/sdk/nat/v2/_proxy.py @@ -13,17 +13,15 @@ from openstack import proxy - class Proxy(proxy.Proxy): - def gateways(self, **attrs): - return self._list(_nat_gateway.NatGateway, **attrs) +# NAT Gateway def create_gateway(self, **attrs): """Create a new gateway from attributes :param dict attrs: Keyword arguments which will be used to create - a :class:`~otcextensions.sdk.nat.v2.nat_gateway.NatGateway + a :class:`~otcextensions.sdk.nat.v2.nat_gateway.NatGateway` """ return self._create(_nat_gateway.NatGateway, **attrs) @@ -31,6 +29,42 @@ def delete_gateway(self, id): """Create a new gateway from attributes :param dict attrs: Keyword arguments which will be used to create - a :class:`~otcextensions.sdk.nat.v2.nat_gateway.NatGateway + a :class:`~otcextensions.sdk.nat.v2.nat_gateway.NatGateway` """ return self._delete(_nat_gateway.NatGateway, id=id) + + def gateways(self, **attrs): + """Return a generator of NAT Gateways + + :param kwargs query: Optional query parameters to be sent to limit + the resources being returned. + :returns: A generator of NAT Gateway objects + :rtype: :class:`~otcextensions.sdk.nat.v2.nat_gateway.NatGateway` + """ + return self._list(_nat_gateway.NatGateway, **attrs) + + def get_nat_gateway(self, nat_gateway): + """Get a single Nat Gateway + + :param nat_gateway: The value can be the ID of a NAT Gatway or a + :class:`~otcextensions.sdk.nat.v2.nat_gateway.NatGateway` + instance. + + :returns: One :class:`~otcextensions.sdk.nat.v2.nat_gateway.NatGateway` + :raises: :class:`~openstack.exceptions.ResourceNotFound` + when no resource can be found. + """ + return self._get(_nat_gateway.NatGateway, nat_gateway) + + def update_nat_gateway(self, nat_gateway, **attrs): + """Update a NAT Gateway + + :param nat_gateway: Either the ID of a NAT Gateway or a + :class:`~otcextensions.sdk.nat.v2.nat_gateway.NatGateway` instance. + :attrs kwargs: The attributes to update on the server represented + by ``server``. + + :returns: The updated NAT Gateway + :rtype: :class:`~otcextensions.sdk.nat.v2.nat_gateway.NatGateway` + """ + return self._update(_server.Server, server, **attrs) diff --git a/otcextensions/sdk/nat/v2/dnat.py b/otcextensions/sdk/nat/v2/dnat.py index 5c71f7e2c..35a46c40b 100644 --- a/otcextensions/sdk/nat/v2/dnat.py +++ b/otcextensions/sdk/nat/v2/dnat.py @@ -11,10 +11,8 @@ # under the License. from openstack import resource - class Dnat(resource.Resource): resources_key = 'dnat_rules' - resource_key = 'dnat_rule' base_path = '/dnat_rules' # capabilities @@ -22,48 +20,38 @@ class Dnat(resource.Resource): allow_fetch = True allow_delete = True allow_list = True - - _query_mapping = resource.QueryParameters( - 'admin_state_up', 'cidr', 'created_at', 'external_service_port', - 'floating_ip_address', 'floating_ip_id', 'id', - 'internal_service_port', 'limit', 'nat_gateway_id', 'network_id', - 'port_id', 'private_id', 'protocol', 'source_type', 'status', - 'project_id' - ) - + # Properties - #: Specifies whether DNAT rule is enabled / disabled - #: *true:* DNAT rule is enabled - #: *false:* DNAT rule is disabled - admin_state_up = resource.Body('admin_state_up', type=bool) - #: Specifies when the rule is created. - #: The format is yyyy-mm-dd hh:mm:ss. - created_at = resource.Body('created_at') - #: Specifies the port for providing external services. - external_service_port = resource.Body('external_service_port', type=int) - #: Specifies the EIP - floating_ip_address = resource.Body('floating_ip_address') - #: Specifies the EIP ID - floating_ip_id = resource.Body('floating_ip_id') - #: Specifies the gateway ID. - gateway_id = resource.Body('gateway_id') - #: Specifies the ID of the DNAT rule. id = resource.Body('id') - #: Specifies port used by ECS/BMS to provide services for external systems - internal_service_port = resource.Body('internal_service_port', type=int) - #: Specifies the ID of the NAT gateway. + #: Specifies the ID of the DNAT rule. + tenant_id = resource.Body('tenant_id') + #: Specifies the project ID. nat_gateway_id = resource.Body('nat_gateway_id') + #: Specifies the NAT Gateway ID. + port_id = resource.Body('port_id') #: Specifies the port ID of an ECS or BMS #: Parameter is used in the VPC scenario. #: This parameter is an alternative to private_ip - port_id = resource.Body('port_id') + private_ip = resource.Body('private_ip') #: Specifies the IP address of a Direct Connect connection. #: Parameter is used in the Direct Connect scenario. #: This parameter is an alternative to port_id. - private_ip = resource.Body('private_ip') - #: Specifies the project ID. - project_id = resource.Body('tenant_id') - #: Specifies the protocol type. Currently TCP(6), UDP(17) and ANY(0) + internal_service_port = resource.Body('internal_service_port', type=int) + #: Specifies port used by ECS/BMS to provide services for external systems + floating_ip_id = resource.Body('floating_ip_id') + #: Specifies the EIP ID + floating_ip_address = resource.Body('floating_ip_address') + #: Specifies the EIP + external_service_port = resource.Body('external_service_port') + #: Specifies the port for providing external services. protocol = resource.Body('protocol') - #: Specifies the status of the DNAT rule + #: Specifies the protocol type. Currently TCP(6), UDP(17) and ANY(0) status = resource.Body('status') + #: Specifies the status of the DNAT rule + admin_state_up = resource.Body('admin_state_up', type=bool) + #: Specifies whether DNAT rule is enabled / disabled + #: *true:* DNAT rule is enabled + #: *false:* DNAT rule is disabled + created_at = resource.Body('created_at') + #: Specifies when the rule is created. + #: The format is yyyy-mm-dd hh:mm:ss. diff --git a/otcextensions/sdk/nat/v2/nat_gateway.py b/otcextensions/sdk/nat/v2/nat_gateway.py index d87da1924..b33776bf7 100644 --- a/otcextensions/sdk/nat/v2/nat_gateway.py +++ b/otcextensions/sdk/nat/v2/nat_gateway.py @@ -17,10 +17,11 @@ class NatGateway(resource.Resource): # capabilities allow_create = True + allow_fetch = True + allow_commit = True allow_delete = True allow_list = True - #allow_get = True - + # Properties #: Specifies the ID of the NAT gateway. id = resource.Body('id') diff --git a/otcextensions/sdk/nat/v2/snat.py b/otcextensions/sdk/nat/v2/snat.py index 57c75685f..b9f49619e 100644 --- a/otcextensions/sdk/nat/v2/snat.py +++ b/otcextensions/sdk/nat/v2/snat.py @@ -11,10 +11,8 @@ # under the License. from openstack import resource - class Snat(resource.Resource): resources_key = 'snat_rules' - resource_key = 'snat_rule' base_path = '/snat_rules' # capabilities @@ -22,41 +20,35 @@ class Snat(resource.Resource): allow_fetch = True allow_delete = True allow_list = True - - _query_mapping = resource.QueryParameters( - 'admin_state_up', 'cidr', 'created_at', 'floating_ip_address', - 'floating_ip_id', 'id', 'limit', 'nat_gateway_id', 'network_id', - 'source_type', 'status', 'project_id' - ) - + # Properties - #: Specifies the status of the SNAT rule - admin_state_up = resource.Body('admin_state_up', type=bool) - #: Specifies a subset of the VPC subnet CIDR block or a - #: CIDR block of Direct Connect connection. - cidr = resource.Body('cidr') - #: Specifies when the rule is created. - #: The format is yyyy-mm-dd hh:mm:ss. - created_at = resource.Body('created_at') - #: Specifies the EIP - #: Multiple EIPs are separated using commas - floating_ip_address = resource.Body('floating_ip_address') - #: Specifies the EIP ID - #: Multiple EIPs are separated using commas - floating_ip_id = resource.Body('floating_ip_id') - #: Specifies the ID of the SNAT rule. id = resource.Body('id') - #: Specifies the gateway ID. + #: Specifies the ID of the SNAT rule. + tenant_id = resource.Body('tenant_id') + #: Specifies the project ID. nat_gateway_id = resource.Body('nat_gateway_id') - #: Specifies the network ID + #: Specifies the NAT Gateway ID. network_id = resource.Body('network_id') - #: Specifies the project ID. - project_id = resource.Body('tenant_id') + #: Specifies the network ID + cidr = resource.Body('cidr') + #: Specifies a subset of the VPC subnet CIDR block or a + #: CIDR block of Direct Connect connection. + source_type = resource.Body('source_type', type=int) #: *0:* Either network_id or cidr can be specified in VPC #: *1:* only cidr can be specified over a Direct Connect connection #: Default: 0 - source_type = resource.Body('source_type', type=int) + floating_ip_id = resource.Body('floating_ip_id') + #: Specifies the EIP ID + #: Multiple EIPs are separated using commas + floating_ip_address = resource.Body('floating_ip_address') + #: Specifies the EIP + #: Multiple EIPs are separated using commas + status = resource.Body('status') + #: Specifies the status of the SNAT rule + admin_state_up = resource.Body('admin_state_up', type=bool) #: Specifies whether SNAT rule is enabled / disabled #: *true:* SNAT rule is enabled #: *false:* SNAT rule is disabled - status = resource.Body('status') + created_at = resource.Body('created_at') + #: Specifies when the rule is created. + #: The format is yyyy-mm-dd hh:mm:ss. \ No newline at end of file From d1cb7bf3770f33b1f8a6eb5ad3c1199101091925 Mon Sep 17 00:00:00 2001 From: "T. Schreiber" Date: Tue, 12 Nov 2019 14:51:25 +0000 Subject: [PATCH 03/73] dnat and snat proxy functions added --- otcextensions/sdk/nat/v2/_proxy.py | 90 +++++++++++++++++++++++++++++- 1 file changed, 87 insertions(+), 3 deletions(-) diff --git a/otcextensions/sdk/nat/v2/_proxy.py b/otcextensions/sdk/nat/v2/_proxy.py index 36cd1f64e..3a21b133a 100644 --- a/otcextensions/sdk/nat/v2/_proxy.py +++ b/otcextensions/sdk/nat/v2/_proxy.py @@ -10,6 +10,8 @@ # License for the specific language governing permissions and limitations # under the License. from otcextensions.sdk.nat.v2 import nat_gateway as _nat_gateway +from otcextensions.sdk.nat.v2 import snat as _snat +from otcextensions.sdk.nat.v2 import dnat as _dnat from openstack import proxy @@ -26,7 +28,7 @@ def create_gateway(self, **attrs): return self._create(_nat_gateway.NatGateway, **attrs) def delete_gateway(self, id): - """Create a new gateway from attributes + """Delete a NAT gateway :param dict attrs: Keyword arguments which will be used to create a :class:`~otcextensions.sdk.nat.v2.nat_gateway.NatGateway` @@ -61,10 +63,92 @@ def update_nat_gateway(self, nat_gateway, **attrs): :param nat_gateway: Either the ID of a NAT Gateway or a :class:`~otcextensions.sdk.nat.v2.nat_gateway.NatGateway` instance. - :attrs kwargs: The attributes to update on the server represented + :attrs attrs: The attributes to update on the server represented by ``server``. :returns: The updated NAT Gateway :rtype: :class:`~otcextensions.sdk.nat.v2.nat_gateway.NatGateway` """ - return self._update(_server.Server, server, **attrs) + return self._update(_nat_gateway, nat_gateway, **attrs) + +# SNAT rules + + def create_snat_rule(self, **attrs): + """Create a new SNAT rule from attributes + + :param dict attrs: Keyword arguments which will be used to create + a :class:`~otcextensions.sdk.nat.v2.snat.Snat` + """ + return self._create(_snat.Snat, **attrs) + + def delete_snat_rule(self, id): + """Delete a SNAT rule + + :param dict attrs: Keyword arguments which will be used to create + a :class:`~otcextensions.sdk.nat.v2.snat.Snat` + """ + return self._delete(_snat.Snat, id=id) + + def get_snat_rule(self, snat_rule): + """Get a single SNAT rule + + :param snat_rule: The value can be the ID of a SNAT rule or a + :class:`~otcextensions.sdk.nat.v2.snat.Snat` + instance. + + :returns: One :class:`~otcextensions.sdk.nat.v2.snat.Snat` + :raises: :class:`~openstack.exceptions.ResourceNotFound` + when no resource can be found. + """ + return self._get(_snat.Snat, snat_rule) + + def snat_rules(self, **attrs): + """Return a generator of SNAT rules + + :param attrs query: Optional query parameters to be sent to limit + the resources being returned. + :returns: A generator of NAT Gateway objects + :rtype: :class:`~otcextensions.sdk.nat.v2.snat.SNAT` + """ + return self._list(_snat.Snat, **attrs) + +# DNAT rules + + def create_dnat_rule(self, **attrs): + """Create a new DNAT rule from attributes + + :param dict attrs: Keyword arguments which will be used to create + a :class:`~otcextensions.sdk.nat.v2.dnat.Dnat` + """ + return self._create(_dnat.Dnat, **attrs) + + def delete_dnat_rule(self, id): + """Delete a DNAT rule + + :param dict attrs: Keyword arguments which will be used to create + a :class:`~otcextensions.sdk.nat.v2.dnat.Dnat` + """ + return self._delete(_dnat.Dnat, id=id) + + def get_dnat_rule(self, dnat_rule): + """Get a single DNAT rule + + :param dnat_rule: The value can be the ID of a DNAT rule or a + :class:`~otcextensions.sdk.nat.v2.dnat.Dnat` + instance. + + :returns: One :class:`~otcextensions.sdk.nat.v2.dnat.Dnat` + :raises: :class:`~openstack.exceptions.ResourceNotFound` + when no resource can be found. + """ + return self._get(_dnat.Dnat, dnat_rule) + + def dnat_rules(self, **attrs): + """Return a generator of DNAT rules + + :param attrs query: Optional query parameters to be sent to limit + the resources being returned. + :returns: A generator of DNAT rules objects + :rtype: :class:`~otcextensions.sdk.nat.v2.dnat.Dnat` + """ + return self._list(_dnat.Dnat, **attrs) \ No newline at end of file From d47071b55cd6005fd7bf34ffc3fd68c9dad01e60 Mon Sep 17 00:00:00 2001 From: "T. Schreiber" Date: Fri, 15 Nov 2019 13:36:12 +0000 Subject: [PATCH 04/73] first running state --- otcextensions/sdk/nat/v2/_proxy.py | 2 ++ otcextensions/sdk/nat/v2/nat_gateway.py | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/otcextensions/sdk/nat/v2/_proxy.py b/otcextensions/sdk/nat/v2/_proxy.py index 3a21b133a..080ffe71e 100644 --- a/otcextensions/sdk/nat/v2/_proxy.py +++ b/otcextensions/sdk/nat/v2/_proxy.py @@ -17,6 +17,8 @@ class Proxy(proxy.Proxy): + skip_discovery = True + # NAT Gateway def create_gateway(self, **attrs): diff --git a/otcextensions/sdk/nat/v2/nat_gateway.py b/otcextensions/sdk/nat/v2/nat_gateway.py index b33776bf7..a7951d81c 100644 --- a/otcextensions/sdk/nat/v2/nat_gateway.py +++ b/otcextensions/sdk/nat/v2/nat_gateway.py @@ -13,6 +13,7 @@ class NatGateway(resource.Resource): resources_key = 'nat_gateways' + resource_key = 'nat_gateway' base_path = '/nat_gateways' # capabilities @@ -37,7 +38,7 @@ class NatGateway(resource.Resource): #: *2:* medium type, supports up to 50,000 SNAT connections #: *3:* large type, supports up to 200,000 SNAT connections #: *4:* extra-large type, supports up to 1,000,000 SNAT connections - spec = resource.Body('spec', type=int) + spec = resource.Body('spec') #: Specifies the router ID router_id = resource.Body('router_id') #: Specifies the network ID of the downstream interface From 2e6a1f37d6219bac91856c3daa9bd5882b6728e7 Mon Sep 17 00:00:00 2001 From: "T. Schreiber" Date: Fri, 15 Nov 2019 15:07:14 +0000 Subject: [PATCH 05/73] gateway fixed --- otcextensions/sdk/nat/v2/_proxy.py | 50 +++++++++++----------- otcextensions/sdk/nat/v2/dnat.py | 48 ++++++++++----------- otcextensions/sdk/nat/v2/gateway.py | 13 ++---- otcextensions/sdk/nat/v2/nat_gateway.py | 56 ------------------------- otcextensions/sdk/nat/v2/snat.py | 44 +++++++++---------- 5 files changed, 74 insertions(+), 137 deletions(-) delete mode 100644 otcextensions/sdk/nat/v2/nat_gateway.py diff --git a/otcextensions/sdk/nat/v2/_proxy.py b/otcextensions/sdk/nat/v2/_proxy.py index 080ffe71e..8c19bc932 100644 --- a/otcextensions/sdk/nat/v2/_proxy.py +++ b/otcextensions/sdk/nat/v2/_proxy.py @@ -9,7 +9,7 @@ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. -from otcextensions.sdk.nat.v2 import nat_gateway as _nat_gateway +from otcextensions.sdk.nat.v2 import gateway as _gateway from otcextensions.sdk.nat.v2 import snat as _snat from otcextensions.sdk.nat.v2 import dnat as _dnat @@ -19,59 +19,59 @@ class Proxy(proxy.Proxy): skip_discovery = True -# NAT Gateway +# Gateway def create_gateway(self, **attrs): """Create a new gateway from attributes :param dict attrs: Keyword arguments which will be used to create - a :class:`~otcextensions.sdk.nat.v2.nat_gateway.NatGateway` + a :class:`~otcextensions.sdk.nat.v2.gateway.Gateway` """ - return self._create(_nat_gateway.NatGateway, **attrs) + return self._create(_gateway.Gateway, **attrs) def delete_gateway(self, id): - """Delete a NAT gateway + """Delete a gateway :param dict attrs: Keyword arguments which will be used to create - a :class:`~otcextensions.sdk.nat.v2.nat_gateway.NatGateway` + a :class:`~otcextensions.sdk.nat.v2.gateway.Gateway` """ - return self._delete(_nat_gateway.NatGateway, id=id) + return self._delete(_gateway.Gateway, id=id) def gateways(self, **attrs): - """Return a generator of NAT Gateways + """Return a generator of gateways :param kwargs query: Optional query parameters to be sent to limit the resources being returned. - :returns: A generator of NAT Gateway objects - :rtype: :class:`~otcextensions.sdk.nat.v2.nat_gateway.NatGateway` + :returns: A generator of gateway objects + :rtype: :class:`~otcextensions.sdk.nat.v2.gateway.Gateway` """ - return self._list(_nat_gateway.NatGateway, **attrs) + return self._list(_gateway.Gateway, **attrs) - def get_nat_gateway(self, nat_gateway): - """Get a single Nat Gateway + def get_gateway(self, gateway): + """Get a single gateway - :param nat_gateway: The value can be the ID of a NAT Gatway or a - :class:`~otcextensions.sdk.nat.v2.nat_gateway.NatGateway` + :param gateway: The value can be the ID of a NAT Gatway or a + :class:`~otcextensions.sdk.nat.v2.gateway.Gateway` instance. - :returns: One :class:`~otcextensions.sdk.nat.v2.nat_gateway.NatGateway` + :returns: One :class:`~otcextensions.sdk.nat.v2.gateway.Gateway` :raises: :class:`~openstack.exceptions.ResourceNotFound` when no resource can be found. """ - return self._get(_nat_gateway.NatGateway, nat_gateway) + return self._get(_gateway.Gateway, gateway) - def update_nat_gateway(self, nat_gateway, **attrs): - """Update a NAT Gateway + def update_gateway(self, gateway, **attrs): + """Update a gateway - :param nat_gateway: Either the ID of a NAT Gateway or a - :class:`~otcextensions.sdk.nat.v2.nat_gateway.NatGateway` instance. + :param gateway: Either the ID of a gateway or a + :class:`~otcextensions.sdk.nat.v2.gateway.Gateway` instance. :attrs attrs: The attributes to update on the server represented by ``server``. - :returns: The updated NAT Gateway - :rtype: :class:`~otcextensions.sdk.nat.v2.nat_gateway.NatGateway` + :returns: The updated gateway + :rtype: :class:`~otcextensions.sdk.nat.v2.gateway.Gateway` """ - return self._update(_nat_gateway, nat_gateway, **attrs) + return self._update(_gateway.Gateway, gateway, **attrs) # SNAT rules @@ -109,7 +109,7 @@ def snat_rules(self, **attrs): :param attrs query: Optional query parameters to be sent to limit the resources being returned. - :returns: A generator of NAT Gateway objects + :returns: A generator of gateway objects :rtype: :class:`~otcextensions.sdk.nat.v2.snat.SNAT` """ return self._list(_snat.Snat, **attrs) diff --git a/otcextensions/sdk/nat/v2/dnat.py b/otcextensions/sdk/nat/v2/dnat.py index 35a46c40b..4cada2e6f 100644 --- a/otcextensions/sdk/nat/v2/dnat.py +++ b/otcextensions/sdk/nat/v2/dnat.py @@ -22,36 +22,36 @@ class Dnat(resource.Resource): allow_list = True # Properties - id = resource.Body('id') + #: Specifies whether DNAT rule is enabled / disabled + #: *true:* DNAT rule is enabled + #: *false:* DNAT rule is disabled + admin_state_up = resource.Body('admin_state_up', type=bool) + #: Specifies when the rule is created. + #: The format is yyyy-mm-dd hh:mm:ss. + created_at = resource.Body('created_at') + #: Specifies the port for providing external services. + external_service_port = resource.Body('external_service_port') + #: Specifies the EIP + floating_ip_address = resource.Body('floating_ip_address') + #: Specifies the EIP ID + floating_ip_id = resource.Body('floating_ip_id') + #: Specifies the gateway ID. + gateway_id = resource.Body('gateway_id') #: Specifies the ID of the DNAT rule. - tenant_id = resource.Body('tenant_id') - #: Specifies the project ID. - nat_gateway_id = resource.Body('nat_gateway_id') - #: Specifies the NAT Gateway ID. - port_id = resource.Body('port_id') + id = resource.Body('id') + #: Specifies port used by ECS/BMS to provide services for external systems + internal_service_port = resource.Body('internal_service_port', type=int) #: Specifies the port ID of an ECS or BMS #: Parameter is used in the VPC scenario. #: This parameter is an alternative to private_ip - private_ip = resource.Body('private_ip') + port_id = resource.Body('port_id') #: Specifies the IP address of a Direct Connect connection. #: Parameter is used in the Direct Connect scenario. #: This parameter is an alternative to port_id. - internal_service_port = resource.Body('internal_service_port', type=int) - #: Specifies port used by ECS/BMS to provide services for external systems - floating_ip_id = resource.Body('floating_ip_id') - #: Specifies the EIP ID - floating_ip_address = resource.Body('floating_ip_address') - #: Specifies the EIP - external_service_port = resource.Body('external_service_port') - #: Specifies the port for providing external services. - protocol = resource.Body('protocol') + private_ip = resource.Body('private_ip') #: Specifies the protocol type. Currently TCP(6), UDP(17) and ANY(0) - status = resource.Body('status') + protocol = resource.Body('protocol') #: Specifies the status of the DNAT rule - admin_state_up = resource.Body('admin_state_up', type=bool) - #: Specifies whether DNAT rule is enabled / disabled - #: *true:* DNAT rule is enabled - #: *false:* DNAT rule is disabled - created_at = resource.Body('created_at') - #: Specifies when the rule is created. - #: The format is yyyy-mm-dd hh:mm:ss. + status = resource.Body('status') + #: Specifies the project ID. + tenant_id = resource.Body('tenant_id') \ No newline at end of file diff --git a/otcextensions/sdk/nat/v2/gateway.py b/otcextensions/sdk/nat/v2/gateway.py index bcacd7f32..cf5dc99f4 100644 --- a/otcextensions/sdk/nat/v2/gateway.py +++ b/otcextensions/sdk/nat/v2/gateway.py @@ -11,7 +11,6 @@ # under the License. from openstack import resource - class Gateway(resource.Resource): resources_key = 'nat_gateways' resource_key = 'nat_gateway' @@ -23,13 +22,7 @@ class Gateway(resource.Resource): allow_commit = True allow_delete = True allow_list = True - - _query_mapping = resource.QueryParameters( - 'admin_state_up', 'created_at', 'description', 'id', - 'internal_network_id', 'limit', 'name', 'router_id', - 'spec', 'status', 'project_id' - ) - + # Properties #: Specifies whether GW is up or down #: *true:* Gw is up @@ -47,8 +40,6 @@ class Gateway(resource.Resource): #: Specifies the name of the gateway. #: Contains only digits, letters, underscores and hyphens name = resource.Body('name') - #: Specifies the project ID - project_id = resource.Body('tenant_id') #: Specifies the router ID router_id = resource.Body('router_id') #: Specifies the type of the gateway. @@ -59,3 +50,5 @@ class Gateway(resource.Resource): spec = resource.Body('spec') #: Specifies the status status = resource.Body('status') + #: Specifies the project ID + tenant_id = resource.Body('tenant_id') \ No newline at end of file diff --git a/otcextensions/sdk/nat/v2/nat_gateway.py b/otcextensions/sdk/nat/v2/nat_gateway.py deleted file mode 100644 index a7951d81c..000000000 --- a/otcextensions/sdk/nat/v2/nat_gateway.py +++ /dev/null @@ -1,56 +0,0 @@ -# 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. -from openstack import resource - -class NatGateway(resource.Resource): - resources_key = 'nat_gateways' - resource_key = 'nat_gateway' - base_path = '/nat_gateways' - - # capabilities - allow_create = True - allow_fetch = True - allow_commit = True - allow_delete = True - allow_list = True - - # Properties - #: Specifies the ID of the NAT gateway. - id = resource.Body('id') - #: Specifies the project ID - tenant_id = resource.Body('tenant_id') - #: Specifies the name of the NAT gateway. - #: Contains only digits, letters, underscores and hyphens - name = resource.Body('name') - #: Provides description of NAT Gateway - description = resource.Body('description') - #: Specifies the type of the NAT gateway. - #: *1:* small type, supports up to 10,000 SNAT connections - #: *2:* medium type, supports up to 50,000 SNAT connections - #: *3:* large type, supports up to 200,000 SNAT connections - #: *4:* extra-large type, supports up to 1,000,000 SNAT connections - spec = resource.Body('spec') - #: Specifies the router ID - router_id = resource.Body('router_id') - #: Specifies the network ID of the downstream interface - internal_network_id = resource.Body('internal_network_id') - #: Specifies the status - status = resource.Body('status') - #: Specifies whether GW is up or down - #: *true:* Gw is up - #: *false:* GW is down - admin_state_up = resource.Body('admin_state_up', type=bool) - #: Specifies when GW was is created - #: format is *yyyy-mm-dd hh:mm:ss* - created_at = resource.Body('created_at') - - diff --git a/otcextensions/sdk/nat/v2/snat.py b/otcextensions/sdk/nat/v2/snat.py index b9f49619e..53467da1b 100644 --- a/otcextensions/sdk/nat/v2/snat.py +++ b/otcextensions/sdk/nat/v2/snat.py @@ -22,33 +22,33 @@ class Snat(resource.Resource): allow_list = True # Properties - id = resource.Body('id') - #: Specifies the ID of the SNAT rule. - tenant_id = resource.Body('tenant_id') - #: Specifies the project ID. - nat_gateway_id = resource.Body('nat_gateway_id') - #: Specifies the NAT Gateway ID. - network_id = resource.Body('network_id') - #: Specifies the network ID - cidr = resource.Body('cidr') + #: Specifies the status of the SNAT rule + admin_state_up = resource.Body('admin_state_up', type=bool) #: Specifies a subset of the VPC subnet CIDR block or a #: CIDR block of Direct Connect connection. - source_type = resource.Body('source_type', type=int) - #: *0:* Either network_id or cidr can be specified in VPC - #: *1:* only cidr can be specified over a Direct Connect connection - #: Default: 0 - floating_ip_id = resource.Body('floating_ip_id') - #: Specifies the EIP ID + cidr = resource.Body('cidr') + #: Specifies when the rule is created. + #: The format is yyyy-mm-dd hh:mm:ss. + created_at = resource.Body('created_at') + #: Specifies the EIP #: Multiple EIPs are separated using commas floating_ip_address = resource.Body('floating_ip_address') - #: Specifies the EIP + #: Specifies the EIP ID #: Multiple EIPs are separated using commas - status = resource.Body('status') - #: Specifies the status of the SNAT rule - admin_state_up = resource.Body('admin_state_up', type=bool) + floating_ip_id = resource.Body('floating_ip_id') + #: Specifies the gateway ID. + gateway_id = resource.Body('gateway_id') + #: Specifies the ID of the SNAT rule. + id = resource.Body('id') + #: Specifies the network ID + network_id = resource.Body('network_id') + #: *0:* Either network_id or cidr can be specified in VPC + #: *1:* only cidr can be specified over a Direct Connect connection + #: Default: 0 + source_type = resource.Body('source_type', type=int) #: Specifies whether SNAT rule is enabled / disabled #: *true:* SNAT rule is enabled #: *false:* SNAT rule is disabled - created_at = resource.Body('created_at') - #: Specifies when the rule is created. - #: The format is yyyy-mm-dd hh:mm:ss. \ No newline at end of file + status = resource.Body('status') + #: Specifies the project ID. + tenant_id = resource.Body('tenant_id') \ No newline at end of file From fd2785a47714a0b259cd9d39229320b806e1f1dd Mon Sep 17 00:00:00 2001 From: "T. Schreiber" Date: Fri, 15 Nov 2019 15:22:44 +0000 Subject: [PATCH 06/73] linting corrections --- otcextensions/sdk/nat/v2/_proxy.py | 6 ++++-- otcextensions/sdk/nat/v2/dnat.py | 5 +++-- otcextensions/sdk/nat/v2/gateway.py | 5 +++-- otcextensions/sdk/nat/v2/snat.py | 9 +++++---- 4 files changed, 15 insertions(+), 10 deletions(-) diff --git a/otcextensions/sdk/nat/v2/_proxy.py b/otcextensions/sdk/nat/v2/_proxy.py index 8c19bc932..cca88af90 100644 --- a/otcextensions/sdk/nat/v2/_proxy.py +++ b/otcextensions/sdk/nat/v2/_proxy.py @@ -15,6 +15,7 @@ from openstack import proxy + class Proxy(proxy.Proxy): skip_discovery = True @@ -64,7 +65,8 @@ def update_gateway(self, gateway, **attrs): """Update a gateway :param gateway: Either the ID of a gateway or a - :class:`~otcextensions.sdk.nat.v2.gateway.Gateway` instance. + :class:`~otcextensions.sdk.nat.v2.gateway.Gateway` + instance. :attrs attrs: The attributes to update on the server represented by ``server``. @@ -153,4 +155,4 @@ def dnat_rules(self, **attrs): :returns: A generator of DNAT rules objects :rtype: :class:`~otcextensions.sdk.nat.v2.dnat.Dnat` """ - return self._list(_dnat.Dnat, **attrs) \ No newline at end of file + return self._list(_dnat.Dnat, **attrs) diff --git a/otcextensions/sdk/nat/v2/dnat.py b/otcextensions/sdk/nat/v2/dnat.py index 4cada2e6f..c26f928ac 100644 --- a/otcextensions/sdk/nat/v2/dnat.py +++ b/otcextensions/sdk/nat/v2/dnat.py @@ -11,6 +11,7 @@ # under the License. from openstack import resource + class Dnat(resource.Resource): resources_key = 'dnat_rules' base_path = '/dnat_rules' @@ -20,7 +21,7 @@ class Dnat(resource.Resource): allow_fetch = True allow_delete = True allow_list = True - + # Properties #: Specifies whether DNAT rule is enabled / disabled #: *true:* DNAT rule is enabled @@ -54,4 +55,4 @@ class Dnat(resource.Resource): #: Specifies the status of the DNAT rule status = resource.Body('status') #: Specifies the project ID. - tenant_id = resource.Body('tenant_id') \ No newline at end of file + tenant_id = resource.Body('tenant_id') diff --git a/otcextensions/sdk/nat/v2/gateway.py b/otcextensions/sdk/nat/v2/gateway.py index cf5dc99f4..8080521f9 100644 --- a/otcextensions/sdk/nat/v2/gateway.py +++ b/otcextensions/sdk/nat/v2/gateway.py @@ -11,6 +11,7 @@ # under the License. from openstack import resource + class Gateway(resource.Resource): resources_key = 'nat_gateways' resource_key = 'nat_gateway' @@ -22,7 +23,7 @@ class Gateway(resource.Resource): allow_commit = True allow_delete = True allow_list = True - + # Properties #: Specifies whether GW is up or down #: *true:* Gw is up @@ -51,4 +52,4 @@ class Gateway(resource.Resource): #: Specifies the status status = resource.Body('status') #: Specifies the project ID - tenant_id = resource.Body('tenant_id') \ No newline at end of file + tenant_id = resource.Body('tenant_id') diff --git a/otcextensions/sdk/nat/v2/snat.py b/otcextensions/sdk/nat/v2/snat.py index 53467da1b..a2e556de3 100644 --- a/otcextensions/sdk/nat/v2/snat.py +++ b/otcextensions/sdk/nat/v2/snat.py @@ -11,6 +11,7 @@ # under the License. from openstack import resource + class Snat(resource.Resource): resources_key = 'snat_rules' base_path = '/snat_rules' @@ -20,16 +21,16 @@ class Snat(resource.Resource): allow_fetch = True allow_delete = True allow_list = True - + # Properties #: Specifies the status of the SNAT rule admin_state_up = resource.Body('admin_state_up', type=bool) - #: Specifies a subset of the VPC subnet CIDR block or a + #: Specifies a subset of the VPC subnet CIDR block or a #: CIDR block of Direct Connect connection. cidr = resource.Body('cidr') #: Specifies when the rule is created. #: The format is yyyy-mm-dd hh:mm:ss. - created_at = resource.Body('created_at') + created_at = resource.Body('created_at') #: Specifies the EIP #: Multiple EIPs are separated using commas floating_ip_address = resource.Body('floating_ip_address') @@ -51,4 +52,4 @@ class Snat(resource.Resource): #: *false:* SNAT rule is disabled status = resource.Body('status') #: Specifies the project ID. - tenant_id = resource.Body('tenant_id') \ No newline at end of file + tenant_id = resource.Body('tenant_id') From 27b2a805a1916e0f50d9cbf289fccca150e7e18a Mon Sep 17 00:00:00 2001 From: "T. Schreiber" Date: Mon, 18 Nov 2019 15:46:18 +0000 Subject: [PATCH 07/73] Minor changes, tested successfully --- otcextensions/sdk/nat/v2/dnat.py | 13 ++++++++++++- otcextensions/sdk/nat/v2/gateway.py | 6 ++++++ otcextensions/sdk/nat/v2/snat.py | 15 +++++++++++---- 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/otcextensions/sdk/nat/v2/dnat.py b/otcextensions/sdk/nat/v2/dnat.py index c26f928ac..fc7f842dd 100644 --- a/otcextensions/sdk/nat/v2/dnat.py +++ b/otcextensions/sdk/nat/v2/dnat.py @@ -14,6 +14,7 @@ class Dnat(resource.Resource): resources_key = 'dnat_rules' + resource_key = 'dnat_rule' base_path = '/dnat_rules' # capabilities @@ -22,6 +23,14 @@ class Dnat(resource.Resource): allow_delete = True allow_list = True + _query_mapping = resource.QueryParameters( + 'admin_state_up', 'cidr', 'created_at', 'external_service_port', + 'floating_ip_address', 'floating_ip_id', 'id', + 'internal_service_port', 'limit', 'nat_gateway_id', 'network_id', + 'port_id', 'private_id', 'protocol', 'source_type', 'status', + 'tenant_id' + ) + # Properties #: Specifies whether DNAT rule is enabled / disabled #: *true:* DNAT rule is enabled @@ -31,7 +40,7 @@ class Dnat(resource.Resource): #: The format is yyyy-mm-dd hh:mm:ss. created_at = resource.Body('created_at') #: Specifies the port for providing external services. - external_service_port = resource.Body('external_service_port') + external_service_port = resource.Body('external_service_port', type=int) #: Specifies the EIP floating_ip_address = resource.Body('floating_ip_address') #: Specifies the EIP ID @@ -42,6 +51,8 @@ class Dnat(resource.Resource): id = resource.Body('id') #: Specifies port used by ECS/BMS to provide services for external systems internal_service_port = resource.Body('internal_service_port', type=int) + #: Specifies the ID of the NAT gateway. + nat_gateway_id = resource.Body('nat_gateway_id') #: Specifies the port ID of an ECS or BMS #: Parameter is used in the VPC scenario. #: This parameter is an alternative to private_ip diff --git a/otcextensions/sdk/nat/v2/gateway.py b/otcextensions/sdk/nat/v2/gateway.py index 8080521f9..0b42f1172 100644 --- a/otcextensions/sdk/nat/v2/gateway.py +++ b/otcextensions/sdk/nat/v2/gateway.py @@ -24,6 +24,12 @@ class Gateway(resource.Resource): allow_delete = True allow_list = True + _query_mapping = resource.QueryParameters( + 'admin_state_up', 'created_at', 'description', 'id', + 'internal_network_id', 'limit', 'name', 'router_id', + 'spec', 'status', 'tenant_id' + ) + # Properties #: Specifies whether GW is up or down #: *true:* Gw is up diff --git a/otcextensions/sdk/nat/v2/snat.py b/otcextensions/sdk/nat/v2/snat.py index a2e556de3..dc8afcc7e 100644 --- a/otcextensions/sdk/nat/v2/snat.py +++ b/otcextensions/sdk/nat/v2/snat.py @@ -14,6 +14,7 @@ class Snat(resource.Resource): resources_key = 'snat_rules' + resource_key = 'snat_rule' base_path = '/snat_rules' # capabilities @@ -22,6 +23,12 @@ class Snat(resource.Resource): allow_delete = True allow_list = True + _query_mapping = resource.QueryParameters( + 'admin_state_up', 'cidr', 'created_at', 'floating_ip_address', + 'floating_ip_id', 'id', 'limit', 'nat_gateway_id', 'network_id', + 'source_type', 'status', 'tenant_id' + ) + # Properties #: Specifies the status of the SNAT rule admin_state_up = resource.Body('admin_state_up', type=bool) @@ -37,12 +44,14 @@ class Snat(resource.Resource): #: Specifies the EIP ID #: Multiple EIPs are separated using commas floating_ip_id = resource.Body('floating_ip_id') - #: Specifies the gateway ID. - gateway_id = resource.Body('gateway_id') #: Specifies the ID of the SNAT rule. id = resource.Body('id') + #: Specifies the gateway ID. + nat_gateway_id = resource.Body('nat_gateway_id') #: Specifies the network ID network_id = resource.Body('network_id') + #: Specifies the project ID. + tenant_id = resource.Body('tenant_id') #: *0:* Either network_id or cidr can be specified in VPC #: *1:* only cidr can be specified over a Direct Connect connection #: Default: 0 @@ -51,5 +60,3 @@ class Snat(resource.Resource): #: *true:* SNAT rule is enabled #: *false:* SNAT rule is disabled status = resource.Body('status') - #: Specifies the project ID. - tenant_id = resource.Body('tenant_id') From a060568de4d33126d597a4c11ad20509981b8667 Mon Sep 17 00:00:00 2001 From: "T. Schreiber" Date: Tue, 19 Nov 2019 15:28:52 +0000 Subject: [PATCH 08/73] unittest nat.test_snat nat.test_dnat and nat.test_gateway added --- otcextensions/tests/unit/sdk/nat/v2/test_dnat.py | 4 ++-- otcextensions/tests/unit/sdk/nat/v2/test_gateway.py | 4 ++-- otcextensions/tests/unit/sdk/nat/v2/test_snat.py | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/otcextensions/tests/unit/sdk/nat/v2/test_dnat.py b/otcextensions/tests/unit/sdk/nat/v2/test_dnat.py index 655773526..60f2c0ac2 100644 --- a/otcextensions/tests/unit/sdk/nat/v2/test_dnat.py +++ b/otcextensions/tests/unit/sdk/nat/v2/test_dnat.py @@ -24,7 +24,7 @@ 'port_id': '9a469561-daac-4c94-88f5-39366e5ea193', 'internal_service_port': 993, 'protocol': 'TCP', - 'project_id': '27e25061336f4af590faeabeb7fcd9a3', + 'tenant_id': '27e25061336f4af590faeabeb7fcd9a3', 'created_at': '2017-11-18 07:54:21.665430', 'id': INSTANCE_ID, 'floating_ip_address': '5.21.11.226', @@ -57,7 +57,7 @@ def test_make_it(self): self.assertEqual(EXAMPLE['internal_service_port'], sot.internal_service_port) self.assertEqual(EXAMPLE['protocol'], sot.protocol) - self.assertEqual(EXAMPLE['project_id'], sot.project_id) + self.assertEqual(EXAMPLE['tenant_id'], sot.tenant_id) self.assertEqual(EXAMPLE['created_at'], sot.created_at) self.assertEqual(EXAMPLE['id'], sot.id) self.assertEqual(EXAMPLE['floating_ip_address'], diff --git a/otcextensions/tests/unit/sdk/nat/v2/test_gateway.py b/otcextensions/tests/unit/sdk/nat/v2/test_gateway.py index 327231eae..ae462908b 100644 --- a/otcextensions/tests/unit/sdk/nat/v2/test_gateway.py +++ b/otcextensions/tests/unit/sdk/nat/v2/test_gateway.py @@ -22,7 +22,7 @@ 'status': 'PENDING_CREATE', 'description': 'Test Gateway Response', 'admin_state_up': True, - 'project_id': '27e25061336f4af590faeabeb7fcd9a3', + 'tenant_id': '27e25061336f4af590faeabeb7fcd9a3', 'created_at': '2017-11-18 07:34:32.203044', 'spec': '2', 'internal_network_id': '89d66639-aacb-4929-969d-07080b0f9fd9', @@ -51,7 +51,7 @@ def test_make_it(self): self.assertEqual(EXAMPLE['status'], sot.status) self.assertEqual(EXAMPLE['description'], sot.description) self.assertEqual(EXAMPLE['admin_state_up'], sot.admin_state_up) - self.assertEqual(EXAMPLE['project_id'], sot.project_id) + self.assertEqual(EXAMPLE['tenant_id'], sot.tenant_id) self.assertEqual(EXAMPLE['created_at'], sot.created_at) self.assertEqual(EXAMPLE['spec'], sot.spec) self.assertEqual(EXAMPLE['internal_network_id'], diff --git a/otcextensions/tests/unit/sdk/nat/v2/test_snat.py b/otcextensions/tests/unit/sdk/nat/v2/test_snat.py index 21cf7ee60..7a801a63f 100644 --- a/otcextensions/tests/unit/sdk/nat/v2/test_snat.py +++ b/otcextensions/tests/unit/sdk/nat/v2/test_snat.py @@ -24,7 +24,7 @@ 'network_id': 'eaad9cd6-2372-4be1-9535-9bd37210ae7b', 'cidr': None, 'source_type': 0, - 'project_id': '27e25061336f4af590faeabeb7fcd9a3', + 'tenant_id': '27e25061336f4af590faeabeb7fcd9a3', 'created_at': '2017-11-18 07:54:21.665430', 'id': INSTANCE_ID, 'floating_ip_address': '5.21.11.226' @@ -54,7 +54,7 @@ def test_make_it(self): self.assertEqual(EXAMPLE['network_id'], sot.network_id) self.assertIsNone(sot.cidr) self.assertEqual(EXAMPLE['source_type'], sot.source_type) - self.assertEqual(EXAMPLE['project_id'], sot.project_id) + self.assertEqual(EXAMPLE['tenant_id'], sot.tenant_id) self.assertEqual(EXAMPLE['created_at'], sot.created_at) self.assertEqual(EXAMPLE['id'], sot.id) self.assertEqual(EXAMPLE['floating_ip_address'], From e9cff783ca12bab768b9a223a547d3bb7d49d19d Mon Sep 17 00:00:00 2001 From: "T. Schreiber" Date: Fri, 6 Dec 2019 14:39:06 +0000 Subject: [PATCH 09/73] nat changes --- otcextensions/sdk/nat/v2/_proxy.py | 92 ++++++++++++++----- otcextensions/sdk/nat/v2/dnat.py | 6 +- otcextensions/sdk/nat/v2/gateway.py | 6 +- otcextensions/sdk/nat/v2/snat.py | 4 +- .../tests/unit/sdk/nat/v2/test_dnat.py | 4 +- .../tests/unit/sdk/nat/v2/test_gateway.py | 4 +- .../tests/unit/sdk/nat/v2/test_snat.py | 4 +- 7 files changed, 82 insertions(+), 38 deletions(-) diff --git a/otcextensions/sdk/nat/v2/_proxy.py b/otcextensions/sdk/nat/v2/_proxy.py index cca88af90..dbb9c7436 100644 --- a/otcextensions/sdk/nat/v2/_proxy.py +++ b/otcextensions/sdk/nat/v2/_proxy.py @@ -20,8 +20,7 @@ class Proxy(proxy.Proxy): skip_discovery = True -# Gateway - + # ======== Gateway ======== def create_gateway(self, **attrs): """Create a new gateway from attributes @@ -30,23 +29,40 @@ def create_gateway(self, **attrs): """ return self._create(_gateway.Gateway, **attrs) +<<<<<<< Updated upstream def delete_gateway(self, id): +======= + def delete_gateway(self, gateway, ignore_missing=True): +>>>>>>> Stashed changes """Delete a gateway - :param dict attrs: Keyword arguments which will be used to create - a :class:`~otcextensions.sdk.nat.v2.gateway.Gateway` + :param gateway: key id or an instance of + :class:`~otcextensions.sdk.nat.v2.gateway.Gateway` + :param bool ignore_missing: When set to ``False`` + :class:`~openstack.exceptions.ResourceNotFound` will be raised when + the gateway does not exist. + When set to ``True``, no exception will be set when attempting to + delete a nonexistent gateway. + + :returns: Gateway been deleted + :rtype: :class:`~otcextensions.sdk.nat.v2.gateway.Gateway` """ +<<<<<<< Updated upstream return self._delete(_gateway.Gateway, id=id) +======= + return self._delete(_gateway.Gateway, gateway, + ignore_missing=ignore_missing) +>>>>>>> Stashed changes - def gateways(self, **attrs): + def gateways(self, **query): """Return a generator of gateways - :param kwargs query: Optional query parameters to be sent to limit + :param dict query: Optional query parameters to be sent to limit the resources being returned. :returns: A generator of gateway objects :rtype: :class:`~otcextensions.sdk.nat.v2.gateway.Gateway` """ - return self._list(_gateway.Gateway, **attrs) + return self._list(_gateway.Gateway, **query) def get_gateway(self, gateway): """Get a single gateway @@ -67,16 +83,15 @@ def update_gateway(self, gateway, **attrs): :param gateway: Either the ID of a gateway or a :class:`~otcextensions.sdk.nat.v2.gateway.Gateway` instance. - :attrs attrs: The attributes to update on the server represented - by ``server``. + :param dict attrs: The attributes to update on the gateway represented + by ``gateway``. :returns: The updated gateway :rtype: :class:`~otcextensions.sdk.nat.v2.gateway.Gateway` """ return self._update(_gateway.Gateway, gateway, **attrs) -# SNAT rules - + # ======== SNAT rules ======== def create_snat_rule(self, **attrs): """Create a new SNAT rule from attributes @@ -85,13 +100,27 @@ def create_snat_rule(self, **attrs): """ return self._create(_snat.Snat, **attrs) +<<<<<<< Updated upstream def delete_snat_rule(self, id): +======= + def delete_snat_rule(self, snat, ignore_missing=True): +>>>>>>> Stashed changes """Delete a SNAT rule - :param dict attrs: Keyword arguments which will be used to create - a :class:`~otcextensions.sdk.nat.v2.snat.Snat` + :param bool ignore_missing: When set to ``False`` + :class:`~openstack.exceptions.ResourceNotFound` will be raised when + the SNAT rule does not exist. + When set to ``True``, no exception will be set when attempting to + delete a nonexistent SNAT rule. + + :returns: SNAT rule been deleted + :rtype: :class:`~otcextensions.sdk.nat.v2.snat.Snat` """ +<<<<<<< Updated upstream return self._delete(_snat.Snat, id=id) +======= + return self._delete(_snat.Snat, snat, ignore_missing=ignore_missing) +>>>>>>> Stashed changes def get_snat_rule(self, snat_rule): """Get a single SNAT rule @@ -106,18 +135,17 @@ def get_snat_rule(self, snat_rule): """ return self._get(_snat.Snat, snat_rule) - def snat_rules(self, **attrs): + def snat_rules(self, **query): """Return a generator of SNAT rules - :param attrs query: Optional query parameters to be sent to limit + :param dict query: Optional query parameters to be sent to limit the resources being returned. - :returns: A generator of gateway objects - :rtype: :class:`~otcextensions.sdk.nat.v2.snat.SNAT` + :returns: A generator of Snat rule objects + :rtype: :class:`~otcextensions.sdk.nat.v2.snat.Snat` """ - return self._list(_snat.Snat, **attrs) - -# DNAT rules + return self._list(_snat.Snat, **query) + # ======== DNAT rules ======== def create_dnat_rule(self, **attrs): """Create a new DNAT rule from attributes @@ -126,13 +154,29 @@ def create_dnat_rule(self, **attrs): """ return self._create(_dnat.Dnat, **attrs) +<<<<<<< Updated upstream def delete_dnat_rule(self, id): +======= + def delete_dnat_rule(self, dnat, ignore_missing=True): +>>>>>>> Stashed changes """Delete a DNAT rule - :param dict attrs: Keyword arguments which will be used to create + :param dict attrs: Keyword arguments which will be used to delete a :class:`~otcextensions.sdk.nat.v2.dnat.Dnat` + :param bool ignore_missing: When set to ``False`` + :class:`~openstack.exceptions.ResourceNotFound` will be raised when + the DNAT rule does not exist. + When set to ``True``, no exception will be set when attempting to + delete a nonexistent DNAT rule. + + :returns: DNAT rule been deleted + :rtype: :class:`~otcextensions.sdk.nat.v2.dnat.Dnat` """ +<<<<<<< Updated upstream return self._delete(_dnat.Dnat, id=id) +======= + return self._delete(_dnat.Dnat, dnat, ignore_missing=ignore_missing) +>>>>>>> Stashed changes def get_dnat_rule(self, dnat_rule): """Get a single DNAT rule @@ -147,12 +191,12 @@ def get_dnat_rule(self, dnat_rule): """ return self._get(_dnat.Dnat, dnat_rule) - def dnat_rules(self, **attrs): + def dnat_rules(self, **query): """Return a generator of DNAT rules - :param attrs query: Optional query parameters to be sent to limit + :param dict query: Optional query parameters to be sent to limit the resources being returned. :returns: A generator of DNAT rules objects :rtype: :class:`~otcextensions.sdk.nat.v2.dnat.Dnat` """ - return self._list(_dnat.Dnat, **attrs) + return self._list(_dnat.Dnat, **query) diff --git a/otcextensions/sdk/nat/v2/dnat.py b/otcextensions/sdk/nat/v2/dnat.py index fc7f842dd..5c71f7e2c 100644 --- a/otcextensions/sdk/nat/v2/dnat.py +++ b/otcextensions/sdk/nat/v2/dnat.py @@ -28,7 +28,7 @@ class Dnat(resource.Resource): 'floating_ip_address', 'floating_ip_id', 'id', 'internal_service_port', 'limit', 'nat_gateway_id', 'network_id', 'port_id', 'private_id', 'protocol', 'source_type', 'status', - 'tenant_id' + 'project_id' ) # Properties @@ -61,9 +61,9 @@ class Dnat(resource.Resource): #: Parameter is used in the Direct Connect scenario. #: This parameter is an alternative to port_id. private_ip = resource.Body('private_ip') + #: Specifies the project ID. + project_id = resource.Body('tenant_id') #: Specifies the protocol type. Currently TCP(6), UDP(17) and ANY(0) protocol = resource.Body('protocol') #: Specifies the status of the DNAT rule status = resource.Body('status') - #: Specifies the project ID. - tenant_id = resource.Body('tenant_id') diff --git a/otcextensions/sdk/nat/v2/gateway.py b/otcextensions/sdk/nat/v2/gateway.py index 0b42f1172..bcacd7f32 100644 --- a/otcextensions/sdk/nat/v2/gateway.py +++ b/otcextensions/sdk/nat/v2/gateway.py @@ -27,7 +27,7 @@ class Gateway(resource.Resource): _query_mapping = resource.QueryParameters( 'admin_state_up', 'created_at', 'description', 'id', 'internal_network_id', 'limit', 'name', 'router_id', - 'spec', 'status', 'tenant_id' + 'spec', 'status', 'project_id' ) # Properties @@ -47,6 +47,8 @@ class Gateway(resource.Resource): #: Specifies the name of the gateway. #: Contains only digits, letters, underscores and hyphens name = resource.Body('name') + #: Specifies the project ID + project_id = resource.Body('tenant_id') #: Specifies the router ID router_id = resource.Body('router_id') #: Specifies the type of the gateway. @@ -57,5 +59,3 @@ class Gateway(resource.Resource): spec = resource.Body('spec') #: Specifies the status status = resource.Body('status') - #: Specifies the project ID - tenant_id = resource.Body('tenant_id') diff --git a/otcextensions/sdk/nat/v2/snat.py b/otcextensions/sdk/nat/v2/snat.py index dc8afcc7e..57c75685f 100644 --- a/otcextensions/sdk/nat/v2/snat.py +++ b/otcextensions/sdk/nat/v2/snat.py @@ -26,7 +26,7 @@ class Snat(resource.Resource): _query_mapping = resource.QueryParameters( 'admin_state_up', 'cidr', 'created_at', 'floating_ip_address', 'floating_ip_id', 'id', 'limit', 'nat_gateway_id', 'network_id', - 'source_type', 'status', 'tenant_id' + 'source_type', 'status', 'project_id' ) # Properties @@ -51,7 +51,7 @@ class Snat(resource.Resource): #: Specifies the network ID network_id = resource.Body('network_id') #: Specifies the project ID. - tenant_id = resource.Body('tenant_id') + project_id = resource.Body('tenant_id') #: *0:* Either network_id or cidr can be specified in VPC #: *1:* only cidr can be specified over a Direct Connect connection #: Default: 0 diff --git a/otcextensions/tests/unit/sdk/nat/v2/test_dnat.py b/otcextensions/tests/unit/sdk/nat/v2/test_dnat.py index 60f2c0ac2..655773526 100644 --- a/otcextensions/tests/unit/sdk/nat/v2/test_dnat.py +++ b/otcextensions/tests/unit/sdk/nat/v2/test_dnat.py @@ -24,7 +24,7 @@ 'port_id': '9a469561-daac-4c94-88f5-39366e5ea193', 'internal_service_port': 993, 'protocol': 'TCP', - 'tenant_id': '27e25061336f4af590faeabeb7fcd9a3', + 'project_id': '27e25061336f4af590faeabeb7fcd9a3', 'created_at': '2017-11-18 07:54:21.665430', 'id': INSTANCE_ID, 'floating_ip_address': '5.21.11.226', @@ -57,7 +57,7 @@ def test_make_it(self): self.assertEqual(EXAMPLE['internal_service_port'], sot.internal_service_port) self.assertEqual(EXAMPLE['protocol'], sot.protocol) - self.assertEqual(EXAMPLE['tenant_id'], sot.tenant_id) + self.assertEqual(EXAMPLE['project_id'], sot.project_id) self.assertEqual(EXAMPLE['created_at'], sot.created_at) self.assertEqual(EXAMPLE['id'], sot.id) self.assertEqual(EXAMPLE['floating_ip_address'], diff --git a/otcextensions/tests/unit/sdk/nat/v2/test_gateway.py b/otcextensions/tests/unit/sdk/nat/v2/test_gateway.py index ae462908b..327231eae 100644 --- a/otcextensions/tests/unit/sdk/nat/v2/test_gateway.py +++ b/otcextensions/tests/unit/sdk/nat/v2/test_gateway.py @@ -22,7 +22,7 @@ 'status': 'PENDING_CREATE', 'description': 'Test Gateway Response', 'admin_state_up': True, - 'tenant_id': '27e25061336f4af590faeabeb7fcd9a3', + 'project_id': '27e25061336f4af590faeabeb7fcd9a3', 'created_at': '2017-11-18 07:34:32.203044', 'spec': '2', 'internal_network_id': '89d66639-aacb-4929-969d-07080b0f9fd9', @@ -51,7 +51,7 @@ def test_make_it(self): self.assertEqual(EXAMPLE['status'], sot.status) self.assertEqual(EXAMPLE['description'], sot.description) self.assertEqual(EXAMPLE['admin_state_up'], sot.admin_state_up) - self.assertEqual(EXAMPLE['tenant_id'], sot.tenant_id) + self.assertEqual(EXAMPLE['project_id'], sot.project_id) self.assertEqual(EXAMPLE['created_at'], sot.created_at) self.assertEqual(EXAMPLE['spec'], sot.spec) self.assertEqual(EXAMPLE['internal_network_id'], diff --git a/otcextensions/tests/unit/sdk/nat/v2/test_snat.py b/otcextensions/tests/unit/sdk/nat/v2/test_snat.py index 7a801a63f..21cf7ee60 100644 --- a/otcextensions/tests/unit/sdk/nat/v2/test_snat.py +++ b/otcextensions/tests/unit/sdk/nat/v2/test_snat.py @@ -24,7 +24,7 @@ 'network_id': 'eaad9cd6-2372-4be1-9535-9bd37210ae7b', 'cidr': None, 'source_type': 0, - 'tenant_id': '27e25061336f4af590faeabeb7fcd9a3', + 'project_id': '27e25061336f4af590faeabeb7fcd9a3', 'created_at': '2017-11-18 07:54:21.665430', 'id': INSTANCE_ID, 'floating_ip_address': '5.21.11.226' @@ -54,7 +54,7 @@ def test_make_it(self): self.assertEqual(EXAMPLE['network_id'], sot.network_id) self.assertIsNone(sot.cidr) self.assertEqual(EXAMPLE['source_type'], sot.source_type) - self.assertEqual(EXAMPLE['tenant_id'], sot.tenant_id) + self.assertEqual(EXAMPLE['project_id'], sot.project_id) self.assertEqual(EXAMPLE['created_at'], sot.created_at) self.assertEqual(EXAMPLE['id'], sot.id) self.assertEqual(EXAMPLE['floating_ip_address'], From c77d7f54abffe23ce2f9c1328ac36d454de0372f Mon Sep 17 00:00:00 2001 From: "T. Schreiber" Date: Fri, 6 Dec 2019 15:18:04 +0000 Subject: [PATCH 10/73] pep8 issues --- otcextensions/sdk/nat/v2/_proxy.py | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/otcextensions/sdk/nat/v2/_proxy.py b/otcextensions/sdk/nat/v2/_proxy.py index dbb9c7436..4df1a1a06 100644 --- a/otcextensions/sdk/nat/v2/_proxy.py +++ b/otcextensions/sdk/nat/v2/_proxy.py @@ -29,11 +29,7 @@ def create_gateway(self, **attrs): """ return self._create(_gateway.Gateway, **attrs) -<<<<<<< Updated upstream - def delete_gateway(self, id): -======= def delete_gateway(self, gateway, ignore_missing=True): ->>>>>>> Stashed changes """Delete a gateway :param gateway: key id or an instance of @@ -47,12 +43,8 @@ def delete_gateway(self, gateway, ignore_missing=True): :returns: Gateway been deleted :rtype: :class:`~otcextensions.sdk.nat.v2.gateway.Gateway` """ -<<<<<<< Updated upstream - return self._delete(_gateway.Gateway, id=id) -======= return self._delete(_gateway.Gateway, gateway, ignore_missing=ignore_missing) ->>>>>>> Stashed changes def gateways(self, **query): """Return a generator of gateways @@ -100,11 +92,7 @@ def create_snat_rule(self, **attrs): """ return self._create(_snat.Snat, **attrs) -<<<<<<< Updated upstream - def delete_snat_rule(self, id): -======= def delete_snat_rule(self, snat, ignore_missing=True): ->>>>>>> Stashed changes """Delete a SNAT rule :param bool ignore_missing: When set to ``False`` @@ -116,11 +104,7 @@ def delete_snat_rule(self, snat, ignore_missing=True): :returns: SNAT rule been deleted :rtype: :class:`~otcextensions.sdk.nat.v2.snat.Snat` """ -<<<<<<< Updated upstream - return self._delete(_snat.Snat, id=id) -======= return self._delete(_snat.Snat, snat, ignore_missing=ignore_missing) ->>>>>>> Stashed changes def get_snat_rule(self, snat_rule): """Get a single SNAT rule @@ -154,11 +138,7 @@ def create_dnat_rule(self, **attrs): """ return self._create(_dnat.Dnat, **attrs) -<<<<<<< Updated upstream - def delete_dnat_rule(self, id): -======= def delete_dnat_rule(self, dnat, ignore_missing=True): ->>>>>>> Stashed changes """Delete a DNAT rule :param dict attrs: Keyword arguments which will be used to delete @@ -172,11 +152,7 @@ def delete_dnat_rule(self, dnat, ignore_missing=True): :returns: DNAT rule been deleted :rtype: :class:`~otcextensions.sdk.nat.v2.dnat.Dnat` """ -<<<<<<< Updated upstream - return self._delete(_dnat.Dnat, id=id) -======= return self._delete(_dnat.Dnat, dnat, ignore_missing=ignore_missing) ->>>>>>> Stashed changes def get_dnat_rule(self, dnat_rule): """Get a single DNAT rule From c38218f3bc68208798c68782c7498197d78ac20e Mon Sep 17 00:00:00 2001 From: "T. Schreiber" Date: Fri, 6 Dec 2019 15:34:18 +0000 Subject: [PATCH 11/73] test_proxy.py added for NAT --- otcextensions/tests/unit/sdk/nat/v2/test_proxy.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/otcextensions/tests/unit/sdk/nat/v2/test_proxy.py b/otcextensions/tests/unit/sdk/nat/v2/test_proxy.py index 9f5140483..5d5ac33f5 100644 --- a/otcextensions/tests/unit/sdk/nat/v2/test_proxy.py +++ b/otcextensions/tests/unit/sdk/nat/v2/test_proxy.py @@ -1,3 +1,5 @@ +<<<<<<< Updated upstream +======= # 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 @@ -85,6 +87,7 @@ def test_dnat_rule_delete(self): def test_dnat_rule_get(self): self.verify_get(self.proxy.get_dnat_rule, dnat.Dnat) - +# move def test_dnat_rules(self): self.verify_list(self.proxy.dnat_rules, dnat.Dnat) +>>>>>>> Stashed changes From aecad159753947c3ee462aca2dfdf511209d492a Mon Sep 17 00:00:00 2001 From: "T. Schreiber" Date: Fri, 6 Dec 2019 15:36:04 +0000 Subject: [PATCH 12/73] stash status changed and proxy test added --- otcextensions/tests/unit/sdk/nat/v2/test_proxy.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/otcextensions/tests/unit/sdk/nat/v2/test_proxy.py b/otcextensions/tests/unit/sdk/nat/v2/test_proxy.py index 5d5ac33f5..9f5140483 100644 --- a/otcextensions/tests/unit/sdk/nat/v2/test_proxy.py +++ b/otcextensions/tests/unit/sdk/nat/v2/test_proxy.py @@ -1,5 +1,3 @@ -<<<<<<< Updated upstream -======= # 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 @@ -87,7 +85,6 @@ def test_dnat_rule_delete(self): def test_dnat_rule_get(self): self.verify_get(self.proxy.get_dnat_rule, dnat.Dnat) -# move + def test_dnat_rules(self): self.verify_list(self.proxy.dnat_rules, dnat.Dnat) ->>>>>>> Stashed changes From 6324d177d6e538b3b932e82421b183210991f290 Mon Sep 17 00:00:00 2001 From: Vineet Pruthi Date: Wed, 29 Jan 2020 10:53:44 +0000 Subject: [PATCH 13/73] Adding osclient code for nat --- otcextensions/osclient/nat/__init__.py | 0 otcextensions/osclient/nat/client.py | 53 ++++ otcextensions/osclient/nat/v2/__init__.py | 0 otcextensions/osclient/nat/v2/dnat.py | 206 ++++++++++++++++ otcextensions/osclient/nat/v2/gateway.py | 226 ++++++++++++++++++ otcextensions/osclient/nat/v2/snat.py | 191 +++++++++++++++ .../tests/unit/osclient/nat/v2/__init__.py | 0 .../tests/unit/osclient/nat/v2/fakes.py | 132 ++++++++++ .../unit/osclient/nat/v2/test_gateway.py | 180 ++++++++++++++ setup.cfg | 15 ++ 10 files changed, 1003 insertions(+) create mode 100644 otcextensions/osclient/nat/__init__.py create mode 100644 otcextensions/osclient/nat/client.py create mode 100644 otcextensions/osclient/nat/v2/__init__.py create mode 100644 otcextensions/osclient/nat/v2/dnat.py create mode 100644 otcextensions/osclient/nat/v2/gateway.py create mode 100644 otcextensions/osclient/nat/v2/snat.py create mode 100644 otcextensions/tests/unit/osclient/nat/v2/__init__.py create mode 100644 otcextensions/tests/unit/osclient/nat/v2/fakes.py create mode 100644 otcextensions/tests/unit/osclient/nat/v2/test_gateway.py diff --git a/otcextensions/osclient/nat/__init__.py b/otcextensions/osclient/nat/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/otcextensions/osclient/nat/client.py b/otcextensions/osclient/nat/client.py new file mode 100644 index 000000000..110ddff6f --- /dev/null +++ b/otcextensions/osclient/nat/client.py @@ -0,0 +1,53 @@ +# 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 logging + +from osc_lib import utils + +from otcextensions import sdk +from otcextensions.i18n import _ + +LOG = logging.getLogger(__name__) + +DEFAULT_API_VERSION = '2' +API_VERSION_OPTION = 'os_nat_api_version' +API_NAME = "nat" +API_VERSIONS = { + "2": "openstack.connection.Connection" +} + + +def make_client(instance): + """Returns a rds proxy""" + + conn = instance.sdk_connection + + if getattr(conn, 'nat', None) is None: + LOG.debug('OTC extensions are not registered. Do that now') + sdk.register_otc_extensions(conn) + + LOG.debug('NAT client initialized using OpenStack OTC SDK: %s', + conn.nat) + return conn.nat + + +def build_option_parser(parser): + """Hook to add global options""" + parser.add_argument( + '--os-nat-api-version', + metavar='', + default=utils.env('OS_NAT_API_VERSION'), + help=_("NAT API version, default=%s " + "(Env: OS_NAT_API_VERSION)") % DEFAULT_API_VERSION + ) + return parser diff --git a/otcextensions/osclient/nat/v2/__init__.py b/otcextensions/osclient/nat/v2/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/otcextensions/osclient/nat/v2/dnat.py b/otcextensions/osclient/nat/v2/dnat.py new file mode 100644 index 000000000..6e10ce625 --- /dev/null +++ b/otcextensions/osclient/nat/v2/dnat.py @@ -0,0 +1,206 @@ +# 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. +# +"""DNAT v2 action implementations""" +import logging + +from osc_lib import utils +from osc_lib.command import command + +from otcextensions.i18n import _ + +LOG = logging.getLogger(__name__) + + +class ListDnatRules(command.Lister): + + _description = _("List DNAT Rules.") + columns = ('Id', 'Nat Gateway Id', 'Port Id', 'Private IP', 'Floating Ip Address', 'Protocol', 'Status') + + def get_parser(self, prog_name): + parser = super(ListDnatRules, self).get_parser(prog_name) + + parser.add_argument( + '--id', + metavar='', + help=_('Specifies the ID of the SNAT rule.')) + parser.add_argument( + '--limit', + metavar='', + help=_('Limit to fetch number of records.')) + parser.add_argument( + '--project-id', + metavar='', + help=_('Specifies the project ID.')) + parser.add_argument( + '--nat-gateway-id', + metavar='', + help=_('Specifies the NAT gateway ID.')) + parser.add_argument( + '--port-id', + metavar='', + help=_('Specifies the port ID of an ECS or a BMS.')) + parser.add_argument( + '--private-ip', + metavar='', + help=_('Specifies the private IP address, for example,the IP address of a Direct Connect connection.')) + parser.add_argument( + '--internal-service-port', + metavar='', + help=_('Specifies port used by ECSs or BMSs toprovide services for external systems.')) + parser.add_argument( + '--floating-ip-id', + metavar='', + help=_('Specifies the EIP ID.')) + parser.add_argument( + '--floating-ip-address', + metavar='', + help=_('Specifies the EIP.')) + parser.add_argument( + '--external-service-port', + metavar='', + help=_('Specifies the port for providing external services.')) + parser.add_argument( + '--protocol', + metavar='', + help=_('Specifies the protocol type.')) + parser.add_argument( + '--status', + metavar='', + help=_('Specifies the status of the DNAT rule.')) + parser.add_argument( + '--admin-state-up', + metavar='', + help=_('Specifies whether the DNAT rule is enabled or disabled.')) + parser.add_argument( + '--created-at', + metavar='', + help=_('Specifies when the DNAT rule is created (UTC time). ' + 'Its valuerounds to 6 decimal places forseconds. ' + 'The format is yyyy-mm-ddhh:mm:ss.')) + + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.nat + args_list = [ + 'id', 'limit', 'tenant_id', 'nat_gateway_id', 'port_id', 'private_ip', 'internal_service_port', 'floating_ip_id', 'floating_ip_address', 'external_service_port', 'protocol', 'status', 'admin_state_up', 'created_at' + ] + attrs = {} + for arg in args_list: + if getattr(parsed_args, arg): + attrs[arg] = getattr(parsed_args, arg) + + data = client.dnat_rules(**args) + + return ( + self.columns, + (utils.get_item_properties( + s, + self.columns, + ) for s in data) + ) + + +class ShowDnatRule(command.ShowOne): + _description = _("Show Dnat Rule details") + + def get_parser(self, prog_name): + parser = super(ShowDnatRule, self).get_parser(prog_name) + parser.add_argument( + 'dnat_rule_id', + metavar='', + help=_('Specifies the ID of the SNAT Rule'), + ) + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.nat + obj = client.get_dnat_rule(parsed_args.dnat_rule_id) + + display_columns, columns = _get_columns(obj) + data = utils.get_item_properties(obj, columns) + + return (display_columns, data) + + +class CreateDnatRule(command.ShowOne): + _description = _("Create new DNAT Rule") + + def get_parser(self, prog_name): + parser = super(CreateDnatRule, self).get_parser(prog_name) + parser.add_argument( + 'nat_gateway_id', + metavar="", + help=_("Specifies the ID of the NAT gateway")) + parser.add_argument( + '--port-id', + metavar='', + help=_('Specifies the port ID of an ECS or a BMS.')) + parser.add_argument( + '--private-ip', + metavar='', + help=_('Specifies the private IP address, for example,the IP address of a Direct Connect connection.')) + parser.add_argument( + '--internal-service-port', + metavar='', + help=_('Specifies port used by ECSs or BMSs toprovide services for external systems.')) + parser.add_argument( + 'floating_ip_id', + metavar="", + help=_("Specifies the EIP ID. Multiple EIPs are separated using commas")) + parser.add_argument( + '--external-service-port', + metavar='', + help=_('Specifies the port for providing external services.')) + parser.add_argument( + '--protocol', + metavar='', + help=_('Specifies the protocol type.')) + + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.nat + + args_list = ['nat_gateway_id', 'port_id', 'private_ip', 'internal_service_port', 'floating_ip_id', 'external_service_port', 'protocol'] + attrs = {} + for arg in args_list: + if getattr(parsed_args, arg): + attrs[arg] = getattr(parsed_args, arg) + + obj = client.create_dnat_rule(**attrs) + + display_columns, columns = _get_columns(obj) + data = utils.get_item_properties(obj, columns) + + return (display_columns, data) + + +class DeleteDnatRule(command.Command): + + _description = _("Deletes Dnat Rule(s).") + + def get_parser(self, prog_name): + parser = super(DeleteDnatRule, self).get_parser(prog_name) + parser.add_argument( + 'dnat_rule_id', + metavar='', + help=_('Specifies the ID of the DNAT Rule'), + ) + + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.nat + dnat_rule = client.get_dnat_rule(parsed_args.dnat_rule_id) + return client.delete_dnat_rule(dnat_rule.id) diff --git a/otcextensions/osclient/nat/v2/gateway.py b/otcextensions/osclient/nat/v2/gateway.py new file mode 100644 index 000000000..abc8a965b --- /dev/null +++ b/otcextensions/osclient/nat/v2/gateway.py @@ -0,0 +1,226 @@ +# 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. +# +"""NAT Gateway v2 action implementations""" +import logging + +from osc_lib import utils +from osc_lib.command import command + +from otcextensions.i18n import _ + +LOG = logging.getLogger(__name__) + + +class ListNatGateway(command.Lister): + + _description = _("List Nat Gateway.") + columns = ('Id', 'Name', 'Spec', 'Router Id', 'Status') + + def get_parser(self, prog_name): + parser = super(ListNatGateway, self).get_parser(prog_name) + + parser.add_argument( + '--id', + metavar='', + help=_('Specifies the ID of the NAT Gateway.')) + parser.add_argument( + '--limit', + metavar='', + help=_('Limit to fetch number of records.')) + parser.add_argument( + '--project-id', + metavar='', + help=_('Specifies the project ID.')) + parser.add_argument( + '--name', + metavar='', + help=_('Specifies the Name of the NAT Gateway.')) + parser.add_argument( + '--spec', + metavar='', + help=_('Specifies the type of the NAT Gateway.')) + parser.add_argument( + '--router-id', + metavar='', + help=_('Specifies the router ID.')) + parser.add_argument( + '--internal-network-id', + metavar='', + help=_('Specifies the network ID.')) + parser.add_argument( + '--status', + metavar='', + help=_('Specifies the status of the NAT Gateway.')) + parser.add_argument( + '--admin-state-up', + metavar='', + help=_('Specifies whether the NAT Gateway is enabled or disabled.')) + parser.add_argument( + '--created-at', + metavar='', + help=_('Specifies when the NAT Gateway is created (UTC time). ' + 'Its valuerounds to 6 decimal places forseconds. ' + 'The format is yyyy-mm-ddhh:mm:ss.')) + + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.nat + args_list = [ + 'id', 'limit', 'tenant_id', 'name', 'description', 'spec', 'router_id', 'internal_network_id', 'status', 'admin_state_up', 'created_at' + ] + attrs = {} + for arg in args_list: + if getattr(parsed_args, arg): + attrs[arg] = getattr(parsed_args, arg) + + data = client.gateways(**args) + + return ( + self.columns, + (utils.get_item_properties( + s, + self.columns, + ) for s in data) + ) + + +class ShowNatGateway(command.ShowOne): + _description = _("Show NAT Gateway details") + + def get_parser(self, prog_name): + parser = super(ShowNatGateway, self).get_parser(prog_name) + parser.add_argument( + 'nat_gateway_id', + metavar='', + help=_('Specifies the ID of the NAT Gateway.'), + ) + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.nat + obj = client.get_gateway(parsed_args.nat_gateway_id) + + display_columns, columns = _get_columns(obj) + data = utils.get_item_properties(obj, columns) + + return (display_columns, data) + + +class CreateNatGateway(command.ShowOne): + _description = _("Create new NAT Gateway") + + def get_parser(self, prog_name): + parser = super(CreateNatGateway, self).get_parser(prog_name) + parser.add_argument( + 'name', + metavar="", + help=_("Specifies the name of the NAT Gateway.")) + parser.add_argument( + '--description', + metavar="", + help=_("Provides supplementary informationabout the NAT gateway.")) + parser.add_argument( + '--spec', + metavar="", + help=_("Specifies the type of the NAT gateway.")) + parser.add_argument( + '--router-id', + metavar="", + help=_("Specifies the VPC ID")) + parser.add_argument( + '--internal-network-id', + metavar="", + help=_("Specifies the network ID of thedownstream interface " + "(the next hop ofthe DVR) of the NAT gateway.")) + + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.nat + + args_list = ['name', 'description', 'spec', 'router_id', 'internal_network_id'] + attrs = {} + for arg in args_list: + if getattr(parsed_args, arg): + attrs[arg] = getattr(parsed_args, arg) + + obj = client.create_gateway(**attrs) + + display_columns, columns = _get_columns(obj) + data = utils.get_item_properties(obj, columns) + + return (display_columns, data) + + +class UpdateNatGateway(command.ShowOne): + _description = _("Update a NAT Gateway.") + + def get_parser(self, prog_name): + parser = super(UpdateNatGateway, self).get_parser(prog_name) + parser.add_argument( + 'nat_gateway', + metavar='', + help=_('Specifies the Name or ID of the NAT Gateway.'), + ) + parser.add_argument( + '--name', + metavar="", + help=_("Specifies the name of the NAT Gateway.")) + parser.add_argument( + '--description', + metavar="", + help=_("Provides supplementary informationabout the NAT gateway.")) + parser.add_argument( + '--spec', + metavar="", + help=_("Specifies the type of the NAT gateway.")) + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.nat + args_list = [ + 'name', 'description', 'spec' + ] + attrs = {} + for arg in args_list: + if getattr(parsed_args, arg): + attrs[arg] = getattr(parsed_args, arg) + nat_gateway = client.get_gateway(parsed_args.nat_gateway) + + obj = client.update_gateway(nat_gateway.id, **attrs) + + display_columns, columns = _get_columns(obj) + data = utils.get_item_properties(obj, columns) + + return (display_columns, data) + + +class DeleteNatGateway(command.Command): + + _description = _("Deletes NAT Gateway.") + + def get_parser(self, prog_name): + parser = super(DeleteNatGateway, self).get_parser(prog_name) + parser.add_argument( + 'nat_gateway', + metavar='', + help=_('Specifies the Name or ID of the NAT gateway.'), + ) + + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.nat + nat_gateway = client.get_gateway(parsed_args.nat_gateway) + return client.delete_gateway(nat_gateway.id) diff --git a/otcextensions/osclient/nat/v2/snat.py b/otcextensions/osclient/nat/v2/snat.py new file mode 100644 index 000000000..c87100832 --- /dev/null +++ b/otcextensions/osclient/nat/v2/snat.py @@ -0,0 +1,191 @@ +# 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. +# +"""SNAT v2 action implementations""" +import logging + +from osc_lib import utils +from osc_lib.command import command + +from otcextensions.i18n import _ + +LOG = logging.getLogger(__name__) + + +class ListSnatRules(command.Lister): + + _description = _("List SNAT Rules.") + columns = ('Id', 'Nat Gateway Id', 'Network Id', 'Cidr', 'Floating Ip Address', 'Status') + + def get_parser(self, prog_name): + parser = super(ListSnatRules, self).get_parser(prog_name) + + parser.add_argument( + '--id', + metavar='', + help=_('Specifies the ID of the SNAT rule.')) + parser.add_argument( + '--limit', + metavar='', + help=_('Limit to fetch number of records.')) + parser.add_argument( + '--project-id', + metavar='', + help=_('Specifies the project ID.')) + parser.add_argument( + '--nat-gateway-id', + metavar='', + help=_('Specifies the NAT gateway ID.')) + parser.add_argument( + '--net-id', + metavar='', + help=_('Specifies the network ID used by theSNAT rule.')) + parser.add_argument( + '--cidr', + metavar='', + help=_('Specifies a subset of the VPC subnetCIDR block or a CIDR block of DirectConnect connection.')) + parser.add_argument( + '--source-type', + metavar='', + help=_('Specifies Source Type.')) + parser.add_argument( + '--floating-ip-id', + metavar='', + help=_('Specifies the EIP ID.')) + parser.add_argument( + '--floating-ip-address', + metavar='', + help=_('Specifies the EIP.')) + parser.add_argument( + '--status', + metavar='', + help=_('Specifies the status of the SNATrule.')) + parser.add_argument( + '--admin-state-up', + metavar='', + help=_('Specifies whether the SNAT rule isenabled or disabled.')) + parser.add_argument( + '--created-at', + metavar='', + help=_('Specifies when the SNAT rule iscreated (UTC time). ' + 'Its valuerounds to 6 decimal places forseconds. ' + 'The format is yyyy-mm-ddhh:mm:ss.')) + + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.nat + args_list = [ + 'id', 'limit', 'network_id', 'tenant_id', 'nat_gateway_id', 'network_id', 'cidr', 'source_type', 'floating_ip_id', 'floating_ip_address', 'status', 'admin_state_up', 'created_at' + ] + attrs = {} + for arg in args_list: + if getattr(parsed_args, arg): + attrs[arg] = getattr(parsed_args, arg) + + data = client.snat_rules(**args) + + return ( + self.columns, + (utils.get_item_properties( + s, + self.columns, + ) for s in data) + ) + + +class ShowSnatRule(command.ShowOne): + _description = _("Show Snat Rule details") + + def get_parser(self, prog_name): + parser = super(ShowSnatRule, self).get_parser(prog_name) + parser.add_argument( + 'snat_rule_id', + metavar='', + help=_('Specifies the ID of the SNAT Rule'), + ) + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.nat + obj = client.get_snat_rule(parsed_args.snat_rule_id) + + display_columns, columns = _get_columns(obj) + data = utils.get_item_properties(obj, columns) + + return (display_columns, data) + + +class CreateSnatRule(command.ShowOne): + _description = _("Create new SNAT Rule") + + def get_parser(self, prog_name): + parser = super(CreateSnatRule, self).get_parser(prog_name) + parser.add_argument( + 'nat_gateway_id', + metavar="", + help=_("Specifies the ID of the NAT gateway")) + parser.add_argument( + 'floating_ip_id', + metavar="", + help=_("Specifies the EIP ID. Multiple EIPs are separated using commas")) + parser.add_argument( + '--net-id', + metavar="", + help=_("Specifies the network ID used by the SNATrule. This parameter and cidr arealternative.")) + parser.add_argument( + '--cidr', + metavar="", + help=_("Specifies CIDR, which can be in the formatof a network segment or a host IP address")) + parser.add_argument( + '--source-type', + metavar="", + help=_("Specifies the source type.")) + + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.nat + + args_list = ['nat_gateway_id', 'floating_ip_id', 'network_id', 'cidr', 'source_type'] + attrs = {} + for arg in args_list: + if getattr(parsed_args, arg): + attrs[arg] = getattr(parsed_args, arg) + + obj = client.create_snat_rule(**attrs) + + display_columns, columns = _get_columns(obj) + data = utils.get_item_properties(obj, columns) + + return (display_columns, data) + + +class DeleteSnatRule(command.Command): + + _description = _("Deletes Snat Rule(s).") + + def get_parser(self, prog_name): + parser = super(DeleteSnatRule, self).get_parser(prog_name) + parser.add_argument( + 'snat_rule_id', + metavar='', + help=_('Specifies the ID of the SNAT Rule'), + ) + + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.nat + snat_rule = client.get_snat_rule(parsed_args.snat_rule_id) + return client.delete_snat_rule(snat_rule.id) + diff --git a/otcextensions/tests/unit/osclient/nat/v2/__init__.py b/otcextensions/tests/unit/osclient/nat/v2/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/otcextensions/tests/unit/osclient/nat/v2/fakes.py b/otcextensions/tests/unit/osclient/nat/v2/fakes.py new file mode 100644 index 000000000..215352d16 --- /dev/null +++ b/otcextensions/tests/unit/osclient/nat/v2/fakes.py @@ -0,0 +1,132 @@ +# 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 random +import uuid + +import mock + +from openstackclient.tests.unit import utils + +from otcextensions.tests.unit.osclient import test_base + +from otcextensions.sdk.nat.v2 import gateway +from otcextensions.sdk.nat.v2 import snat +from otcextensions.sdk.nat.v2 import dnat + + +def gen_data(data, columns): + """Fill expected data tuple based on columns list + """ + return tuple(getattr(data, attr, '') for attr in columns) + + +def gen_data_dict(data, columns): + """Fill expected data tuple based on columns list + """ + return tuple(data.get(attr, '') for attr in columns) + + +class TestNat(utils.TestCommand): + def setUp(self): + super(TestRds, self).setUp() + + self.app.client_manager.nat = mock.Mock() + + self.client = self.app.client_manager.nat + + self.nat_gateway_mock = FakeNatGateway + self.snat_rule_mock = FakeSnatRule + self.dnat_rule_mock = FakeDnatRule + + +class FakeNatGateway(test_base.Fake): + """Fake one or more datastore versions.""" + @classmethod + def generate(cls): + """Create a fake datastore. + + :return: + A FakeResource object, with id, name, metadata, and so on + """ + # Set default attributes. + object_info = { + "nat_gateway": { + "id": "id-" + uuid.uuid4().hex, + "name": "name-" + uuid.uuid4().hex, + "router_id": "router-" + uuid.uuid4().hex, + "status": "PENDING_CREATE", + "description": "my nat gateway", + "admin_state_up": true, + "tenant_id": "tenant-id-" + uuid.uuid4().hex, + "created_at": time.clock() * 1000, + "spec": "1", + "internal_network_id": "net-id-" + uuid.uuid4().hex + } + } + + return datastore.Datastore(**object_info) + + +class FakeSnatRule(test_base.Fake): + """Fake one or more Instance.""" + @classmethod + def generate(cls): + """Create a fake Configuration. + + :return: + A FakeResource object, with id, name, metadata, and so on + """ + + # Set default attributes. + object_info = { + "snat_rule": { + "id": "id-", + "floating_ip_id": "eip-id-" + uuid.uuid4().hex, + "status": "PENDING_CREATE", + "nat_gateway_id": "gw-id-" + uuid.uuid4().hex, + "admin_state_up": true, + "network_id": "net-id-" + uuid.uuid4().hex, + "cidr": null, + "source_type":0, + "tenant_id": "tenant-id-" + uuid.uuid4().hex, + "created_at": time.clock() * 1000, + "floating_ip_address": uuid.uuid4().hex + } + } + + return snat.Snat.existing(**object_info) + + +class FakeDnatRule(test_base.Fake): + """Fake one or more Backup""" + @classmethod + def generate(cls): + object_info = { + "dnat_rule": { + "id": "id-", + "floating_ip_id": "eip-id-" + uuid.uuid4().hex, + "status": "ACTIVE", + "nat_gateway_id": "gw-id-" + uuid.uuid4().hex, + "admin_state_up": true, + "private_ip": uuid.uuid4().hex, + "internal_service_port": 0, + "protocol": "any", + "tenant_id": "abc", + "created_at": time.clock() * 1000, + "floating_ip_address": uuid.uuid4().hex, + "external_service_port": 0 + } + } + + obj = dnat.Dnat.existing(**object_info) + return obj diff --git a/otcextensions/tests/unit/osclient/nat/v2/test_gateway.py b/otcextensions/tests/unit/osclient/nat/v2/test_gateway.py new file mode 100644 index 000000000..ef9821551 --- /dev/null +++ b/otcextensions/tests/unit/osclient/nat/v2/test_gateway.py @@ -0,0 +1,180 @@ +# 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 osc_lib import exceptions + +from otcextensions.osclient.nat.v2 import gateway +from otcextensions.tests.unit.osclient.nat.v2 import fakes + + +class TestListNatGateways(fakes.TestNat): + + objects = fakes.FakeNatGateway.create_multiple(3) + + column_list_headers = ( + 'Id', 'Name', 'Router Id', 'Status', 'description', 'admin state up', 'Tenant Id', 'Spec', 'Created at' + ) + + columns = ( + 'Id', 'Name', 'Spec', 'Router Id', 'Status' + ) + + data = [] + + for s in objects: + data.append( + (s.id, s.name, s.souter_id, s.status, s.description, s.admin_state_up, s.tenant_id, s.spec, s.created_at)) + + def setUp(self): + super(TestListNatGateways, self).setUp() + + self.cmd = gateway.ListNatGateways(self.app, None) + + self.client.gateways = mock.Mock() + self.client.api_mock = self.client.gateways + + def test_list(self): + arglist = [] + + verifylist = [] + + # Verify cm is triggered with default parameters + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + # Set the response + self.client.api_mock.side_effect = [self.objects] + + # Trigger the action + columns, data = self.cmd.take_action(parsed_args) + + self.client.api_mock.assert_called_with() + + self.assertEqual(self.column_list_headers, columns) + self.assertEqual(self.data, list(data)) + + def test_list_args(self): + arglist = [ + '--limit', '1', + '--id', '2', + '--name', '3', + '--tenant-id', 'abc', + '--description', 'test', + '--spec', '1', + '--router-id', '6', + '--internal-network-id', '7', + '--admin-state-up', 'true', + '--created-at', '20', + ] + + verifylist = [ + ('limit', 1), + ('id', '2'), + ('name', '3'), + ('project_id', 'abc'), + ('description', 'test'), + ('spec', '1'), + ('router_id', '6'), + ('internal_network_id', '7'), + ('admin_state_up', 'true'), + ('created_at', '20'), + ] + + # Verify cm is triggered with default parameters + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + # Trigger the action + columns, data = self.cmd.take_action(parsed_args) + + self.client.api_mock.assert_called_with( + limit='1', + id='2', + name='3', + project_id='abc', + description=test, + spec='1', + router_id='6', + internal_network_id='7', + admin_state_up='true', + created_at='20' + ) + + +class TestShowNatGateway(fakes.TestNat): + + _data = fakes.FakeNatGateway.create_one() + + columns = ( + 'id', 'name', 'internal network id', 'spec', 'router id', 'tenant id', 'status', 'description', 'admin state up' + ) + + data = fakes.gen_data(_data, columns) + + def setUp(self): + super(TestShowNatGateway, self).setUp() + + self.cmd = gateway.ShowNatGateway(self.app, None) + + self.client.get_gateway = mock.Mock(return_value=self._data) + + def test_show(self): + arglist = [ + 'test_gateway', + ] + + verifylist = [ + ('gateway', 'test_gateway'), + ] + + # Verify cm is triggered with default parameters + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + # Trigger the action + columns, data = self.cmd.take_action(parsed_args) + self.client.get_gateway.assert_called_with('test_gateway', + ignore_missing=False) + + self.assertEqual(self.columns, columns) + self.assertEqual(self.data, data) + + +class TestDeleteNatGateway(fakes.TestNat): + + data = fakes.FakeNatGateway.create_one() + + def setUp(self): + super(TestDeleteNatGateway, self).setUp() + + self.cmd = gateway.DeleteNatGateway(self.app, None) + + self.client.get_gateway = mock.Mock(return_value=self.data) + self.client.delete_gateway = mock.Mock(return_value=self.data) + + def test_delete(self): + arglist = [ + 'test_gateway', + ] + + verifylist = [ + ('nat_gateway', 'test_gateway'), + ] + + # Verify cm is triggered with default parameters + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + # Trigger the action + self.cmd.take_action(parsed_args) + + self.client.get_gateway.assert_called_with('nat_gateway_id_or_name') + + self.client.delete_gateway.assert_called_with(self.data.id) diff --git a/setup.cfg b/setup.cfg index cc13ea867..fd0d82758 100644 --- a/setup.cfg +++ b/setup.cfg @@ -102,6 +102,21 @@ openstack.rds.v3 = rds_backup_delete = otcextensions.osclient.rds.v3.backup:DeleteBackup rds_backup_download_links = otcextensions.osclient.rds.v3.backup:ListBackupDownloadLinks +openstack.nat.v2 = + nat_gateway_list = otcextensions.osclient.nat.v2.gateway:ListNatGateways + nat_gateway_show = otcextensions.osclient.nat.v2.gateway:ShowNatGateway + nat_gateway_create = otcextensions.osclient.nat.v2.gateway:CreateNatGateway + nat_gateway_update = otcextensions.osclient.nat.v2.gateway:UpdateNatGateway + nat_gateway_delete = otcextensions.osclient.nat.v2.gateway:DeleteNatGateway + nat_snat_rule_list = otcextensions.osclient.nat.v2.snat:ListSnatRules + nat_snat_rule_show = otcextensions.osclient.nat.v2.snat:ShowSnatRule + nat_snat_rule_create = otcextensions.osclient.nat.v2.snat:CreateSnatRule + nat_snat_rule_delete = otcextensions.osclient.nat.v2.snat:DeleteSnatRule + nat_dnat_rule_list = otcextensions.osclient.nat.v2.dnat:ListDnatRules + nat_dnat_rule_show = otcextensions.osclient.nat.v2.dnat:ShowDnatRule + nat_dnat_rule_create = otcextensions.osclient.nat.v2.dnat:CreateDnatRule + nat_dnat_rule_delete = otcextensions.osclient.nat.v2.dnat:DeleteDnatRule + openstack.auto_scaling.v1 = as_group_list = otcextensions.osclient.auto_scaling.v1.group:ListAutoScalingGroup as_group_show = otcextensions.osclient.auto_scaling.v1.group:ShowAutoScalingGroup From 77156eae3c4978fd7769f6ccebf72891463d23c2 Mon Sep 17 00:00:00 2001 From: Vineet Pruthi Date: Mon, 3 Feb 2020 04:29:05 +0000 Subject: [PATCH 14/73] Fixed error and adding unit tests for osclient --- otcextensions/osclient/nat/v2/dnat.py | 61 ++++- otcextensions/osclient/nat/v2/gateway.py | 52 +++-- otcextensions/osclient/nat/v2/snat.py | 72 ++++-- .../tests/unit/osclient/nat/__init__.py | 0 .../tests/unit/osclient/nat/v2/fakes.py | 81 +++---- .../tests/unit/osclient/nat/v2/test_dnat.py | 216 ++++++++++++++++++ .../unit/osclient/nat/v2/test_gateway.py | 65 +++--- .../tests/unit/osclient/nat/v2/test_snat.py | 211 +++++++++++++++++ .../tests/unit/sdk/nat/v2/__init__.py | 0 setup.cfg | 1 + 10 files changed, 642 insertions(+), 117 deletions(-) create mode 100644 otcextensions/tests/unit/osclient/nat/__init__.py create mode 100644 otcextensions/tests/unit/osclient/nat/v2/test_dnat.py create mode 100644 otcextensions/tests/unit/osclient/nat/v2/test_snat.py create mode 100644 otcextensions/tests/unit/sdk/nat/v2/__init__.py diff --git a/otcextensions/osclient/nat/v2/dnat.py b/otcextensions/osclient/nat/v2/dnat.py index 6e10ce625..813fd860f 100644 --- a/otcextensions/osclient/nat/v2/dnat.py +++ b/otcextensions/osclient/nat/v2/dnat.py @@ -17,14 +17,29 @@ from osc_lib.command import command from otcextensions.i18n import _ +from otcextensions.common import sdk_utils LOG = logging.getLogger(__name__) +def _get_columns(item): + column_map = { + } + return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map) + + class ListDnatRules(command.Lister): _description = _("List DNAT Rules.") - columns = ('Id', 'Nat Gateway Id', 'Port Id', 'Private IP', 'Floating Ip Address', 'Protocol', 'Status') + columns = ( + 'Id', + 'Nat Gateway Id', + 'Port Id', + 'Private IP', + 'Floating Ip Address', + 'Protocol', + 'Status' + ) def get_parser(self, prog_name): parser = super(ListDnatRules, self).get_parser(prog_name) @@ -36,10 +51,12 @@ def get_parser(self, prog_name): parser.add_argument( '--limit', metavar='', + type=int, help=_('Limit to fetch number of records.')) parser.add_argument( '--project-id', metavar='', + dest='tenant_id', help=_('Specifies the project ID.')) parser.add_argument( '--nat-gateway-id', @@ -52,11 +69,13 @@ def get_parser(self, prog_name): parser.add_argument( '--private-ip', metavar='', - help=_('Specifies the private IP address, for example,the IP address of a Direct Connect connection.')) + help=_('Specifies the private IP address, for example, ' + 'the IP address of a Direct Connect connection.')) parser.add_argument( '--internal-service-port', metavar='', - help=_('Specifies port used by ECSs or BMSs toprovide services for external systems.')) + help=_('Specifies port used by ECSs or BMSs toprovide ' + 'services for external systems.')) parser.add_argument( '--floating-ip-id', metavar='', @@ -93,14 +112,27 @@ def get_parser(self, prog_name): def take_action(self, parsed_args): client = self.app.client_manager.nat args_list = [ - 'id', 'limit', 'tenant_id', 'nat_gateway_id', 'port_id', 'private_ip', 'internal_service_port', 'floating_ip_id', 'floating_ip_address', 'external_service_port', 'protocol', 'status', 'admin_state_up', 'created_at' + 'id', + 'limit', + 'tenant_id', + 'nat_gateway_id', + 'port_id', + 'private_ip', + 'internal_service_port', + 'floating_ip_id', + 'floating_ip_address', + 'external_service_port', + 'protocol', + 'status', + 'admin_state_up', + 'created_at' ] attrs = {} for arg in args_list: if getattr(parsed_args, arg): attrs[arg] = getattr(parsed_args, arg) - data = client.dnat_rules(**args) + data = client.dnat_rules(**attrs) return ( self.columns, @@ -149,15 +181,18 @@ def get_parser(self, prog_name): parser.add_argument( '--private-ip', metavar='', - help=_('Specifies the private IP address, for example,the IP address of a Direct Connect connection.')) + help=_('Specifies the private IP address, for example, ' + 'the IP address of a Direct Connect connection.')) parser.add_argument( '--internal-service-port', metavar='', - help=_('Specifies port used by ECSs or BMSs toprovide services for external systems.')) + help=_('Specifies port used by ECSs or BMSs toprovide ' + 'services for external systems.')) parser.add_argument( 'floating_ip_id', metavar="", - help=_("Specifies the EIP ID. Multiple EIPs are separated using commas")) + help=_('Specifies the EIP ID. Multiple EIPs are ' + 'separated using commas')) parser.add_argument( '--external-service-port', metavar='', @@ -172,7 +207,15 @@ def get_parser(self, prog_name): def take_action(self, parsed_args): client = self.app.client_manager.nat - args_list = ['nat_gateway_id', 'port_id', 'private_ip', 'internal_service_port', 'floating_ip_id', 'external_service_port', 'protocol'] + args_list = [ + 'nat_gateway_id', + 'port_id', + 'private_ip', + 'internal_service_port', + 'floating_ip_id', + 'external_service_port', + 'protocol' + ] attrs = {} for arg in args_list: if getattr(parsed_args, arg): diff --git a/otcextensions/osclient/nat/v2/gateway.py b/otcextensions/osclient/nat/v2/gateway.py index abc8a965b..14bfd14cb 100644 --- a/otcextensions/osclient/nat/v2/gateway.py +++ b/otcextensions/osclient/nat/v2/gateway.py @@ -17,17 +17,24 @@ from osc_lib.command import command from otcextensions.i18n import _ +from otcextensions.common import sdk_utils LOG = logging.getLogger(__name__) -class ListNatGateway(command.Lister): +def _get_columns(item): + column_map = { + } + return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map) + + +class ListNatGateways(command.Lister): _description = _("List Nat Gateway.") columns = ('Id', 'Name', 'Spec', 'Router Id', 'Status') def get_parser(self, prog_name): - parser = super(ListNatGateway, self).get_parser(prog_name) + parser = super(ListNatGateways, self).get_parser(prog_name) parser.add_argument( '--id', @@ -36,10 +43,12 @@ def get_parser(self, prog_name): parser.add_argument( '--limit', metavar='', + type=int, help=_('Limit to fetch number of records.')) parser.add_argument( '--project-id', metavar='', + dest='tenant_id', help=_('Specifies the project ID.')) parser.add_argument( '--name', @@ -64,7 +73,8 @@ def get_parser(self, prog_name): parser.add_argument( '--admin-state-up', metavar='', - help=_('Specifies whether the NAT Gateway is enabled or disabled.')) + help=_('Specifies whether the NAT Gateway is enabled ' + 'or disabled.')) parser.add_argument( '--created-at', metavar='', @@ -77,22 +87,25 @@ def get_parser(self, prog_name): def take_action(self, parsed_args): client = self.app.client_manager.nat args_list = [ - 'id', 'limit', 'tenant_id', 'name', 'description', 'spec', 'router_id', 'internal_network_id', 'status', 'admin_state_up', 'created_at' - ] + 'id', + 'limit', + 'tenant_id', + 'name', + 'spec', + 'router_id', + 'internal_network_id', + 'status', + 'admin_state_up', + 'created_at'] attrs = {} for arg in args_list: if getattr(parsed_args, arg): attrs[arg] = getattr(parsed_args, arg) - data = client.gateways(**args) + data = client.gateways(**attrs) - return ( - self.columns, - (utils.get_item_properties( - s, - self.columns, - ) for s in data) - ) + return (self.columns, (utils.get_item_properties(s, self.columns) + for s in data)) class ShowNatGateway(command.ShowOne): @@ -101,15 +114,15 @@ class ShowNatGateway(command.ShowOne): def get_parser(self, prog_name): parser = super(ShowNatGateway, self).get_parser(prog_name) parser.add_argument( - 'nat_gateway_id', - metavar='', + 'nat_gateway', + metavar='', help=_('Specifies the ID of the NAT Gateway.'), ) return parser def take_action(self, parsed_args): client = self.app.client_manager.nat - obj = client.get_gateway(parsed_args.nat_gateway_id) + obj = client.get_gateway(parsed_args.nat_gateway) display_columns, columns = _get_columns(obj) data = utils.get_item_properties(obj, columns) @@ -149,7 +162,12 @@ def get_parser(self, prog_name): def take_action(self, parsed_args): client = self.app.client_manager.nat - args_list = ['name', 'description', 'spec', 'router_id', 'internal_network_id'] + args_list = [ + 'name', + 'description', + 'spec', + 'router_id', + 'internal_network_id'] attrs = {} for arg in args_list: if getattr(parsed_args, arg): diff --git a/otcextensions/osclient/nat/v2/snat.py b/otcextensions/osclient/nat/v2/snat.py index c87100832..4391769d5 100644 --- a/otcextensions/osclient/nat/v2/snat.py +++ b/otcextensions/osclient/nat/v2/snat.py @@ -17,14 +17,28 @@ from osc_lib.command import command from otcextensions.i18n import _ +from otcextensions.common import sdk_utils LOG = logging.getLogger(__name__) +def _get_columns(item): + column_map = { + } + return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map) + + class ListSnatRules(command.Lister): _description = _("List SNAT Rules.") - columns = ('Id', 'Nat Gateway Id', 'Network Id', 'Cidr', 'Floating Ip Address', 'Status') + columns = ( + 'Id', + 'Nat Gateway Id', + 'Network Id', + 'Cidr', + 'Floating Ip Address', + 'Status' + ) def get_parser(self, prog_name): parser = super(ListSnatRules, self).get_parser(prog_name) @@ -36,23 +50,26 @@ def get_parser(self, prog_name): parser.add_argument( '--limit', metavar='', + type=int, help=_('Limit to fetch number of records.')) parser.add_argument( '--project-id', metavar='', + dest='tenant_id', help=_('Specifies the project ID.')) parser.add_argument( '--nat-gateway-id', metavar='', help=_('Specifies the NAT gateway ID.')) parser.add_argument( - '--net-id', + '--network-id', metavar='', help=_('Specifies the network ID used by theSNAT rule.')) parser.add_argument( '--cidr', metavar='', - help=_('Specifies a subset of the VPC subnetCIDR block or a CIDR block of DirectConnect connection.')) + help=_('Specifies a subset of the VPC subnetCIDR block or ' + 'a CIDR block of DirectConnect connection.')) parser.add_argument( '--source-type', metavar='', @@ -85,14 +102,25 @@ def get_parser(self, prog_name): def take_action(self, parsed_args): client = self.app.client_manager.nat args_list = [ - 'id', 'limit', 'network_id', 'tenant_id', 'nat_gateway_id', 'network_id', 'cidr', 'source_type', 'floating_ip_id', 'floating_ip_address', 'status', 'admin_state_up', 'created_at' - ] + 'id', + 'limit', + 'network_id', + 'tenant_id', + 'nat_gateway_id', + 'network_id', + 'cidr', + 'source_type', + 'floating_ip_id', + 'floating_ip_address', + 'status', + 'admin_state_up', + 'created_at'] attrs = {} for arg in args_list: if getattr(parsed_args, arg): attrs[arg] = getattr(parsed_args, arg) - data = client.snat_rules(**args) + data = client.snat_rules(**attrs) return ( self.columns, @@ -132,31 +160,40 @@ def get_parser(self, prog_name): parser = super(CreateSnatRule, self).get_parser(prog_name) parser.add_argument( 'nat_gateway_id', - metavar="", - help=_("Specifies the ID of the NAT gateway")) + metavar='', + help=_('Specifies the ID of the NAT gateway')) parser.add_argument( 'floating_ip_id', - metavar="", - help=_("Specifies the EIP ID. Multiple EIPs are separated using commas")) + metavar='', + help=_('Specifies the EIP ID. Multiple EIPs ' + 'are separated using commas')) parser.add_argument( '--net-id', - metavar="", - help=_("Specifies the network ID used by the SNATrule. This parameter and cidr arealternative.")) + metavar='', + help=_('Specifies the network ID used by the SNAT rule. ' + 'This parameter and cidr arealternative.')) parser.add_argument( '--cidr', - metavar="", - help=_("Specifies CIDR, which can be in the formatof a network segment or a host IP address")) + metavar='', + help=_('Specifies CIDR, which can be in the formatof a ' + 'network segment or a host IP address')) parser.add_argument( '--source-type', - metavar="", - help=_("Specifies the source type.")) + metavar='', + help=_('Specifies the source type.')) return parser def take_action(self, parsed_args): client = self.app.client_manager.nat - args_list = ['nat_gateway_id', 'floating_ip_id', 'network_id', 'cidr', 'source_type'] + args_list = [ + 'nat_gateway_id', + 'floating_ip_id', + 'network_id', + 'cidr', + 'source_type' + ] attrs = {} for arg in args_list: if getattr(parsed_args, arg): @@ -188,4 +225,3 @@ def take_action(self, parsed_args): client = self.app.client_manager.nat snat_rule = client.get_snat_rule(parsed_args.snat_rule_id) return client.delete_snat_rule(snat_rule.id) - diff --git a/otcextensions/tests/unit/osclient/nat/__init__.py b/otcextensions/tests/unit/osclient/nat/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/otcextensions/tests/unit/osclient/nat/v2/fakes.py b/otcextensions/tests/unit/osclient/nat/v2/fakes.py index 215352d16..d746af427 100644 --- a/otcextensions/tests/unit/osclient/nat/v2/fakes.py +++ b/otcextensions/tests/unit/osclient/nat/v2/fakes.py @@ -10,8 +10,8 @@ # License for the specific language governing permissions and limitations # under the License. # -import random import uuid +import time import mock @@ -38,7 +38,7 @@ def gen_data_dict(data, columns): class TestNat(utils.TestCommand): def setUp(self): - super(TestRds, self).setUp() + super(TestNat, self).setUp() self.app.client_manager.nat = mock.Mock() @@ -60,21 +60,19 @@ def generate(cls): """ # Set default attributes. object_info = { - "nat_gateway": { - "id": "id-" + uuid.uuid4().hex, - "name": "name-" + uuid.uuid4().hex, - "router_id": "router-" + uuid.uuid4().hex, - "status": "PENDING_CREATE", - "description": "my nat gateway", - "admin_state_up": true, - "tenant_id": "tenant-id-" + uuid.uuid4().hex, - "created_at": time.clock() * 1000, - "spec": "1", - "internal_network_id": "net-id-" + uuid.uuid4().hex - } + "id": "id-" + uuid.uuid4().hex, + "name": "name-" + uuid.uuid4().hex, + "router_id": "router-" + uuid.uuid4().hex, + "status": "PENDING_CREATE", + "description": "my nat gateway", + "admin_state_up": 'true', + "tenant_id": "tenant-id-" + uuid.uuid4().hex, + "created_at": time.clock() * 1000, + "spec": "1", + "internal_network_id": "net-id-" + uuid.uuid4().hex } - return datastore.Datastore(**object_info) + return gateway.Gateway(**object_info) class FakeSnatRule(test_base.Fake): @@ -89,20 +87,18 @@ def generate(cls): # Set default attributes. object_info = { - "snat_rule": { - "id": "id-", - "floating_ip_id": "eip-id-" + uuid.uuid4().hex, - "status": "PENDING_CREATE", - "nat_gateway_id": "gw-id-" + uuid.uuid4().hex, - "admin_state_up": true, - "network_id": "net-id-" + uuid.uuid4().hex, - "cidr": null, - "source_type":0, - "tenant_id": "tenant-id-" + uuid.uuid4().hex, - "created_at": time.clock() * 1000, - "floating_ip_address": uuid.uuid4().hex - } - } + "id": "id-" + uuid.uuid4().hex, + "floating_ip_id": "eip-id-" + uuid.uuid4().hex, + "status": "PENDING_CREATE", + "nat_gateway_id": "gw-id-" + uuid.uuid4().hex, + "admin_state_up": True, + "network_id": "net-id-" + uuid.uuid4().hex, + "cidr": uuid.uuid4().hex, + "source_type": 0, + "tenant_id": "tenant-id-" + uuid.uuid4().hex, + "created_at": time.clock() * 1000, + "floating_ip_address": uuid.uuid4().hex + } return snat.Snat.existing(**object_info) @@ -112,20 +108,19 @@ class FakeDnatRule(test_base.Fake): @classmethod def generate(cls): object_info = { - "dnat_rule": { - "id": "id-", - "floating_ip_id": "eip-id-" + uuid.uuid4().hex, - "status": "ACTIVE", - "nat_gateway_id": "gw-id-" + uuid.uuid4().hex, - "admin_state_up": true, - "private_ip": uuid.uuid4().hex, - "internal_service_port": 0, - "protocol": "any", - "tenant_id": "abc", - "created_at": time.clock() * 1000, - "floating_ip_address": uuid.uuid4().hex, - "external_service_port": 0 - } + "id": "id-" + uuid.uuid4().hex, + "floating_ip_id": "eip-id-" + uuid.uuid4().hex, + "status": "ACTIVE", + "nat_gateway_id": "gw-id-" + uuid.uuid4().hex, + "admin_state_up": True, + "private_ip": uuid.uuid4().hex, + "internal_service_port": 0, + "protocol": "any", + "tenant_id": "abc", + "port_id": "", + "created_at": time.clock() * 1000, + "floating_ip_address": uuid.uuid4().hex, + "external_service_port": 0 } obj = dnat.Dnat.existing(**object_info) diff --git a/otcextensions/tests/unit/osclient/nat/v2/test_dnat.py b/otcextensions/tests/unit/osclient/nat/v2/test_dnat.py new file mode 100644 index 000000000..f363ccd9a --- /dev/null +++ b/otcextensions/tests/unit/osclient/nat/v2/test_dnat.py @@ -0,0 +1,216 @@ +# 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 otcextensions.osclient.nat.v2 import dnat +from otcextensions.tests.unit.osclient.nat.v2 import fakes + + +class TestListDnatRules(fakes.TestNat): + + objects = fakes.FakeDnatRule.create_multiple(3) + + column_list_headers = ( + 'Id', + 'Nat Gateway Id', + 'Port Id', + 'Private IP', + 'Floating Ip Address', + 'Protocol', + 'Status' + ) + columns = ( + 'id', + 'nat_gateway_id', + 'port_id', + 'private_ip', + 'floating_ip_address', + 'protocol', + 'status' + ) + + data = [] + + for s in objects: + data.append(( + s.id, + s.nat_gateway_id, + s.port_id, + s.private_ip, + s.floating_ip_address, + s.protocol, + s.status + )) + + def setUp(self): + super(TestListDnatRules, self).setUp() + + self.cmd = dnat.ListDnatRules(self.app, None) + + self.client.dnat_rules = mock.Mock() + self.client.api_mock = self.client.dnat_rules + + def test_list(self): + arglist = [] + + verifylist = [] + + # Verify cm is triggered with default parameters + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + # Set the response + self.client.api_mock.side_effect = [self.objects] + + # Trigger the action + columns, data = self.cmd.take_action(parsed_args) + + self.client.api_mock.assert_called_with() + + self.assertEqual(self.column_list_headers, columns) + self.assertEqual(self.data, list(data)) + + def test_list_args(self): + arglist = [ + '--limit', '1', + '--id', '2', + '--nat-gateway-id', '3', + '--project-id', '4', + '--private-ip', '5', + '--internal-service-port', '6', + '--protocol', '7', + '--floating-ip-id', '8', + '--floating-ip-address', '9', + '--admin-state-up', '10', + '--created-at', '11', + '--status', '12' + ] + + verifylist = [ + ('limit', 1), + ('id', '2'), + ('nat_gateway_id', '3'), + ('tenant_id', '4'), + ('private_ip', '5'), + ('internal_service_port', '6'), + ('protocol', '7'), + ('floating_ip_id', '8'), + ('floating_ip_address', '9'), + ('admin_state_up', '10'), + ('created_at', '11'), + ('status', '12'), + ] + + # Verify cm is triggered with default parameters + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + # Set the response + self.client.api_mock.side_effect = [self.objects] + + # Trigger the action + columns, data = self.cmd.take_action(parsed_args) + + self.client.api_mock.assert_called_with( + limit=1, + id='2', + nat_gateway_id='3', + tenant_id='4', + private_ip='5', + internal_service_port='6', + protocol='7', + floating_ip_id='8', + floating_ip_address='9', + admin_state_up='10', + created_at='11', + status='12', + ) + + +class TestShowDnatRule(fakes.TestNat): + + _data = fakes.FakeDnatRule.create_one() + + columns = ( + 'admin_state_up', + 'created_at', + 'external_service_port', + 'floating_ip_address', + 'floating_ip_id', + 'id', + 'internal_service_port', + 'nat_gateway_id', + 'port_id', + 'private_ip', + 'project_id', + 'protocol', + 'status' + ) + + data = fakes.gen_data(_data, columns) + + def setUp(self): + super(TestShowDnatRule, self).setUp() + + self.cmd = dnat.ShowDnatRule(self.app, None) + + self.client.get_dnat_rule = mock.Mock(return_value=self._data) + + def test_show(self): + arglist = [ + 'test_dnat_rule_id', + ] + + verifylist = [ + ('dnat_rule_id', 'test_dnat_rule_id'), + ] + + # Verify cm is triggered with default parameters + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + # Trigger the action + columns, data = self.cmd.take_action(parsed_args) + self.client.get_dnat_rule.assert_called_with('test_dnat_rule_id') + + self.assertEqual(self.columns, columns) + self.assertEqual(self.data, data) + + +class TestDeleteDnatRule(fakes.TestNat): + + data = fakes.FakeDnatRule.create_one() + + def setUp(self): + super(TestDeleteDnatRule, self).setUp() + + self.cmd = dnat.DeleteDnatRule(self.app, None) + + self.client.get_dnat_rule = mock.Mock(return_value=self.data) + self.client.delete_dnat_rule = mock.Mock(return_value=self.data) + + def test_delete(self): + arglist = [ + 'test_dnat_rule_id', + ] + + verifylist = [ + ('dnat_rule_id', 'test_dnat_rule_id'), + ] + + # Verify cm is triggered with default parameters + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + # Trigger the action + self.cmd.take_action(parsed_args) + + self.client.get_dnat_rule.assert_called_with('test_dnat_rule_id') + + self.client.delete_dnat_rule.assert_called_with(self.data.id) diff --git a/otcextensions/tests/unit/osclient/nat/v2/test_gateway.py b/otcextensions/tests/unit/osclient/nat/v2/test_gateway.py index ef9821551..e5487d1c5 100644 --- a/otcextensions/tests/unit/osclient/nat/v2/test_gateway.py +++ b/otcextensions/tests/unit/osclient/nat/v2/test_gateway.py @@ -12,8 +12,6 @@ # import mock -from osc_lib import exceptions - from otcextensions.osclient.nat.v2 import gateway from otcextensions.tests.unit.osclient.nat.v2 import fakes @@ -22,19 +20,15 @@ class TestListNatGateways(fakes.TestNat): objects = fakes.FakeNatGateway.create_multiple(3) - column_list_headers = ( - 'Id', 'Name', 'Router Id', 'Status', 'description', 'admin state up', 'Tenant Id', 'Spec', 'Created at' - ) + column_list_headers = ('Id', 'Name', 'Spec', 'Router Id', 'Status') - columns = ( - 'Id', 'Name', 'Spec', 'Router Id', 'Status' - ) + columns = ('id', 'name', 'spec', 'router_id', 'status') data = [] for s in objects: data.append( - (s.id, s.name, s.souter_id, s.status, s.description, s.admin_state_up, s.tenant_id, s.spec, s.created_at)) + (s.id, s.name, s.spec, s.router_id, s.status)) def setUp(self): super(TestListNatGateways, self).setUp() @@ -68,45 +62,48 @@ def test_list_args(self): '--limit', '1', '--id', '2', '--name', '3', - '--tenant-id', 'abc', - '--description', 'test', - '--spec', '1', + '--project-id', '4', + '--spec', '5', '--router-id', '6', '--internal-network-id', '7', - '--admin-state-up', 'true', - '--created-at', '20', + '--admin-state-up', '8', + '--created-at', '9', + '--status', '10' ] verifylist = [ ('limit', 1), ('id', '2'), ('name', '3'), - ('project_id', 'abc'), - ('description', 'test'), - ('spec', '1'), + ('tenant_id', '4'), + ('spec', '5'), ('router_id', '6'), ('internal_network_id', '7'), - ('admin_state_up', 'true'), - ('created_at', '20'), + ('admin_state_up', '8'), + ('created_at', '9'), + ('status', '10'), ] # Verify cm is triggered with default parameters parsed_args = self.check_parser(self.cmd, arglist, verifylist) + # Set the response + self.client.api_mock.side_effect = [self.objects] + # Trigger the action columns, data = self.cmd.take_action(parsed_args) self.client.api_mock.assert_called_with( - limit='1', + limit=1, id='2', name='3', - project_id='abc', - description=test, - spec='1', + tenant_id='4', + spec='5', router_id='6', internal_network_id='7', - admin_state_up='true', - created_at='20' + admin_state_up='8', + created_at='9', + status='10', ) @@ -115,7 +112,16 @@ class TestShowNatGateway(fakes.TestNat): _data = fakes.FakeNatGateway.create_one() columns = ( - 'id', 'name', 'internal network id', 'spec', 'router id', 'tenant id', 'status', 'description', 'admin state up' + 'admin_state_up', + 'created_at', + 'description', + 'id', + 'internal_network_id', + 'name', + 'project_id', + 'router_id', + 'spec', + 'status' ) data = fakes.gen_data(_data, columns) @@ -133,7 +139,7 @@ def test_show(self): ] verifylist = [ - ('gateway', 'test_gateway'), + ('nat_gateway', 'test_gateway'), ] # Verify cm is triggered with default parameters @@ -141,8 +147,7 @@ def test_show(self): # Trigger the action columns, data = self.cmd.take_action(parsed_args) - self.client.get_gateway.assert_called_with('test_gateway', - ignore_missing=False) + self.client.get_gateway.assert_called_with('test_gateway') self.assertEqual(self.columns, columns) self.assertEqual(self.data, data) @@ -175,6 +180,6 @@ def test_delete(self): # Trigger the action self.cmd.take_action(parsed_args) - self.client.get_gateway.assert_called_with('nat_gateway_id_or_name') + self.client.get_gateway.assert_called_with('test_gateway') self.client.delete_gateway.assert_called_with(self.data.id) diff --git a/otcextensions/tests/unit/osclient/nat/v2/test_snat.py b/otcextensions/tests/unit/osclient/nat/v2/test_snat.py new file mode 100644 index 000000000..c160e3f54 --- /dev/null +++ b/otcextensions/tests/unit/osclient/nat/v2/test_snat.py @@ -0,0 +1,211 @@ +# 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 otcextensions.osclient.nat.v2 import snat +from otcextensions.tests.unit.osclient.nat.v2 import fakes + + +class TestListSnatRules(fakes.TestNat): + + objects = fakes.FakeSnatRule.create_multiple(3) + + column_list_headers = ( + 'Id', + 'Nat Gateway Id', + 'Network Id', + 'Cidr', + 'Floating Ip Address', + 'Status' + ) + columns = ( + 'id', + 'nat_gateway_id', + 'network_id', + 'cidr', + 'floating_ip_address', + 'status' + ) + + data = [] + + for s in objects: + data.append( + s.id, + s.nat_gateway_id, + s.network_id, + s.cidr, + s.floating_ip_address, + s.status + ) + + def setUp(self): + super(TestListSnatRules, self).setUp() + + self.cmd = snat.ListSnatRules(self.app, None) + + self.client.snat_rules = mock.Mock() + self.client.api_mock = self.client.snat_rules + + def test_list(self): + arglist = [] + + verifylist = [] + + # Verify cm is triggered with default parameters + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + # Set the response + self.client.api_mock.side_effect = [self.objects] + + # Trigger the action + columns, data = self.cmd.take_action(parsed_args) + + self.client.api_mock.assert_called_with() + + self.assertEqual(self.column_list_headers, columns) + self.assertEqual(self.data, list(data)) + + def test_list_args(self): + arglist = [ + '--limit', '1', + '--id', '2', + '--nat-gateway-id', '3', + '--network-id', '4', + '--project-id', '5', + '--cidr', '6', + '--source-type', '7', + '--floating-ip-id', '8', + '--floating-ip-address', '9', + '--admin-state-up', '10', + '--created-at', '11', + '--status', '12' + ] + + verifylist = [ + ('limit', 1), + ('id', '2'), + ('nat_gateway_id', '3'), + ('network_id', '4'), + ('tenant_id', '5'), + ('cidr', '6'), + ('source_type', '7'), + ('floating_ip_id', '8'), + ('floating_ip_address', '9'), + ('admin_state_up', '10'), + ('created_at', '11'), + ('status', '12'), + ] + + # Verify cm is triggered with default parameters + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + # Set the response + self.client.api_mock.side_effect = [self.objects] + + # Trigger the action + columns, data = self.cmd.take_action(parsed_args) + + self.client.api_mock.assert_called_with( + limit=1, + id='2', + nat_gateway_id='3', + network_id='4', + tenant_id='5', + cidr='6', + source_type='7', + floating_ip_id='8', + floating_ip_address='9', + admin_state_up='10', + created_at='11', + status='12', + ) + + +class TestShowSnatRule(fakes.TestNat): + + _data = fakes.FakeSnatRule.create_one() + + columns = ( + 'admin_state_up', + 'cidr', + 'created_at', + 'floating_ip_address', + 'floating_ip_id', + 'id', + 'nat_gateway_id', + 'network_id', + 'project_id', + 'source_type', + 'status' + ) + + data = fakes.gen_data(_data, columns) + + def setUp(self): + super(TestShowSnatRule, self).setUp() + + self.cmd = snat.ShowSnatRule(self.app, None) + + self.client.get_snat_rule = mock.Mock(return_value=self._data) + + def test_show(self): + arglist = [ + 'test_snat_rule_id', + ] + + verifylist = [ + ('snat_rule_id', 'test_snat_rule_id'), + ] + + # Verify cm is triggered with default parameters + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + # Trigger the action + columns, data = self.cmd.take_action(parsed_args) + self.client.get_snat_rule.assert_called_with('test_snat_rule_id') + + self.assertEqual(self.columns, columns) + self.assertEqual(self.data, data) + + +class TestDeleteSnatRule(fakes.TestNat): + + data = fakes.FakeSnatRule.create_one() + + def setUp(self): + super(TestDeleteSnatRule, self).setUp() + + self.cmd = snat.DeleteSnatRule(self.app, None) + + self.client.get_snat_rule = mock.Mock(return_value=self.data) + self.client.delete_snat_rule = mock.Mock(return_value=self.data) + + def test_delete(self): + arglist = [ + 'test_snat_rule_id', + ] + + verifylist = [ + ('snat_rule_id', 'test_snat_rule_id'), + ] + + # Verify cm is triggered with default parameters + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + # Trigger the action + self.cmd.take_action(parsed_args) + + self.client.get_snat_rule.assert_called_with('test_snat_rule_id') + + self.client.delete_snat_rule.assert_called_with(self.data.id) diff --git a/otcextensions/tests/unit/sdk/nat/v2/__init__.py b/otcextensions/tests/unit/sdk/nat/v2/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/setup.cfg b/setup.cfg index fd0d82758..6f69f6bdd 100644 --- a/setup.cfg +++ b/setup.cfg @@ -40,6 +40,7 @@ openstack.cli.extension = anti_ddos = otcextensions.osclient.anti_ddos.client dns = otcextensions.osclient.dns.client deh = otcextensions.osclient.deh.client + nat = otcextensions.osclient.nat.client #openstack.obs.v1 = # s3_ls = otcextensions.osclient.obs.v1.ls:List From 10544b7d125b240acf43f35d287cd8ba74605c32 Mon Sep 17 00:00:00 2001 From: Vineet Pruthi Date: Tue, 4 Feb 2020 01:09:45 +0000 Subject: [PATCH 15/73] Minor fix in unit test --- otcextensions/tests/unit/osclient/nat/v2/test_snat.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/otcextensions/tests/unit/osclient/nat/v2/test_snat.py b/otcextensions/tests/unit/osclient/nat/v2/test_snat.py index c160e3f54..a9b739b8d 100644 --- a/otcextensions/tests/unit/osclient/nat/v2/test_snat.py +++ b/otcextensions/tests/unit/osclient/nat/v2/test_snat.py @@ -40,14 +40,14 @@ class TestListSnatRules(fakes.TestNat): data = [] for s in objects: - data.append( + data.append(( s.id, s.nat_gateway_id, s.network_id, s.cidr, s.floating_ip_address, s.status - ) + )) def setUp(self): super(TestListSnatRules, self).setUp() From f057fe919afaadcd0b36683a87c639066c0bc3f3 Mon Sep 17 00:00:00 2001 From: Vineet Pruthi Date: Wed, 19 Feb 2020 11:11:22 +0000 Subject: [PATCH 16/73] Adding functional tests for nat_gateway --- otcextensions/osclient/nat/v2/gateway.py | 8 +- otcextensions/sdk/nat/v2/_proxy.py | 15 ++ otcextensions/sdk/nat/v2/snat.py | 2 +- .../tests/functional/osclient/nat/__init__.py | 0 .../functional/osclient/nat/v2/__init__.py | 0 .../osclient/nat/v2/test_nat_gateway.py | 182 ++++++++++++++++++ .../unit/osclient/nat/v2/test_gateway.py | 8 +- 7 files changed, 206 insertions(+), 9 deletions(-) create mode 100644 otcextensions/tests/functional/osclient/nat/__init__.py create mode 100644 otcextensions/tests/functional/osclient/nat/v2/__init__.py create mode 100644 otcextensions/tests/functional/osclient/nat/v2/test_nat_gateway.py diff --git a/otcextensions/osclient/nat/v2/gateway.py b/otcextensions/osclient/nat/v2/gateway.py index 14bfd14cb..7db142c63 100644 --- a/otcextensions/osclient/nat/v2/gateway.py +++ b/otcextensions/osclient/nat/v2/gateway.py @@ -122,7 +122,7 @@ def get_parser(self, prog_name): def take_action(self, parsed_args): client = self.app.client_manager.nat - obj = client.get_gateway(parsed_args.nat_gateway) + obj = client.find_gateway(parsed_args.nat_gateway) display_columns, columns = _get_columns(obj) data = utils.get_item_properties(obj, columns) @@ -214,7 +214,7 @@ def take_action(self, parsed_args): for arg in args_list: if getattr(parsed_args, arg): attrs[arg] = getattr(parsed_args, arg) - nat_gateway = client.get_gateway(parsed_args.nat_gateway) + nat_gateway = client.find_gateway(parsed_args.nat_gateway) obj = client.update_gateway(nat_gateway.id, **attrs) @@ -240,5 +240,5 @@ def get_parser(self, prog_name): def take_action(self, parsed_args): client = self.app.client_manager.nat - nat_gateway = client.get_gateway(parsed_args.nat_gateway) - return client.delete_gateway(nat_gateway.id) + nat_gateway = client.find_gateway(parsed_args.nat_gateway) + client.delete_gateway(nat_gateway.id) diff --git a/otcextensions/sdk/nat/v2/_proxy.py b/otcextensions/sdk/nat/v2/_proxy.py index 4df1a1a06..bde70a21a 100644 --- a/otcextensions/sdk/nat/v2/_proxy.py +++ b/otcextensions/sdk/nat/v2/_proxy.py @@ -83,6 +83,21 @@ def update_gateway(self, gateway, **attrs): """ return self._update(_gateway.Gateway, gateway, **attrs) + def find_gateway(self, name_or_id, ignore_missing=True): + """Find a single Nat Gateway + + :param name_or_id: The name or ID of a zone + :param bool ignore_missing: When set to ``False`` + :class:`~openstack.exceptions.ResourceNotFound` will be raised + when the gateway does not exist. + When set to ``True``, no exception will be set when attempting + to delete a nonexistent gateway. + + :returns: ``None`` + """ + return self._find(_gateway.Gateway, name_or_id, + ignore_missing=ignore_missing) + # ======== SNAT rules ======== def create_snat_rule(self, **attrs): """Create a new SNAT rule from attributes diff --git a/otcextensions/sdk/nat/v2/snat.py b/otcextensions/sdk/nat/v2/snat.py index 57c75685f..c4fdf5fb5 100644 --- a/otcextensions/sdk/nat/v2/snat.py +++ b/otcextensions/sdk/nat/v2/snat.py @@ -26,7 +26,7 @@ class Snat(resource.Resource): _query_mapping = resource.QueryParameters( 'admin_state_up', 'cidr', 'created_at', 'floating_ip_address', 'floating_ip_id', 'id', 'limit', 'nat_gateway_id', 'network_id', - 'source_type', 'status', 'project_id' + 'source_type', 'status', 'tenant_id' ) # Properties diff --git a/otcextensions/tests/functional/osclient/nat/__init__.py b/otcextensions/tests/functional/osclient/nat/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/otcextensions/tests/functional/osclient/nat/v2/__init__.py b/otcextensions/tests/functional/osclient/nat/v2/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/otcextensions/tests/functional/osclient/nat/v2/test_nat_gateway.py b/otcextensions/tests/functional/osclient/nat/v2/test_nat_gateway.py new file mode 100644 index 000000000..9d861e034 --- /dev/null +++ b/otcextensions/tests/functional/osclient/nat/v2/test_nat_gateway.py @@ -0,0 +1,182 @@ +# 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 json +import uuid + +from openstackclient.tests.functional import base + + +class TestNatGateway(base.TestCase): + """Functional Tests for NAT Gateway""" + + UUID = uuid.uuid4().hex[:8] + ROUTER_NAME = 'sdk-test-router-' + UUID + NET_NAME = 'sdk-test-net-' + UUID + SUBNET_NAME = 'sdk-test-subnet-' + UUID + ROUTER_ID = None + NET_ID = None + + NAT_NAME = 'os-cli-test-' + UUID + NAT_ID = None + + def test_01_nat_gateway_list(self): + self.openstack( + 'nat gateway list -f json ' + ) + + def test_02_gat_gateway_list_filters(self): + self.openstack( + 'nat gateway list ' + '--limit 1 --id 2 ' + '--name 3 --spec 1 ' + '--router-id 123asd ' + '--internal-network-id 123qwe ' + '--status Active ' + '--admin-state-up True ' + ) + + def test_03_nat_gateway_create(self): + self._initialize_network() + json_output = json.loads(self.openstack( + 'nat gateway create {name}' + ' --router-id {router_id}' + ' --internal-network-id {net_id}' + ' --spec {spec} -f json'.format( + name=self.NAT_NAME, + router_id=self.ROUTER_ID, + net_id=self.NET_ID, + description='OTCE Lib Test', + spec=1) + )) + self.assertIsNotNone(json_output) + TestNatGateway.NAT_ID = json_output['id'] + + def test_04_nat_gateway_list_by_id(self): + json_output = json.loads(self.openstack( + 'nat gateway list -f json' + ' --id {}'.format(self.NAT_ID) + )) + self.assertEqual(json_output[0]['Name'], self.NAT_NAME) + self.assertEqual(json_output[0]['Id'], self.NAT_ID) + + def test_05_nat_gateway_list_by_name(self): + json_output = json.loads(self.openstack( + 'nat gateway list -f json' + ' --name {}'.format(self.NAT_NAME) + )) + self.assertEqual(json_output[0]['Name'], self.NAT_NAME) + self.assertEqual(json_output[0]['Id'], self.NAT_ID) + + def test_06_nat_gateway_list_by_router_id(self): + json_output = json.loads(self.openstack( + 'nat gateway list -f json' + ' --router-id {}'.format(self.ROUTER_ID) + )) + for nat_gw in json_output: + self.assertEqual(nat_gw['Router Id'], self.ROUTER_ID) + + def test_07_nat_gateway_show_by_name(self): + json_output = json.loads(self.openstack( + 'nat gateway show -f json ' + self.NAT_NAME + )) + self.assertEqual(json_output['name'], self.NAT_NAME) + self.assertEqual(json_output['id'], self.NAT_ID) + + def test_08_nat_gateway_show_by_id(self): + json_output = json.loads(self.openstack( + 'nat gateway show -f json ' + self.NAT_ID + )) + self.assertEqual(json_output['name'], self.NAT_NAME) + self.assertEqual(json_output['id'], self.NAT_ID) + + def test_09_nat_gateway_update_by_id(self): + name = self.NAT_NAME + "-updated" + description = "otce cli test nat updated" + json_output = json.loads(self.openstack( + 'nat gateway update {nat_id} ' + '--name {name} ' + '--description "{desc}" ' + '-f json'.format( + nat_id=self.NAT_ID, + name=name, + desc=description) + )) + self.assertEqual(json_output['name'], name) + self.assertEqual(json_output['description'], description) + TestNatGateway.NAT_NAME = json_output['name'] + + def test_10_nat_gateway_update_by_name(self): + name = 'os-cli-test-' + self.UUID + description = "otce cli test nat" + json_output = json.loads(self.openstack( + 'nat gateway update {nat_name} ' + '--name {name} ' + '--description "{desc}" ' + '--spec {spec} ' + '-f json'.format( + nat_name=self.NAT_NAME, + name=name, + spec=2, + desc=description) + )) + self.assertEqual(json_output['name'], name) + self.assertEqual(json_output['description'], description) + TestNatGateway.NAT_NAME = json_output['name'] + + def test_11_nat_gateway_delete(self): + self.addCleanup(self._denitialize_network) + self.openstack('nat gateway delete ' + self.NAT_ID) + + def _initialize_network(self): + router = json.loads(self.openstack( + 'router create -f json ' + self.ROUTER_NAME + )) + net = json.loads(self.openstack( + 'network create -f json ' + self.NET_NAME + )) + self.openstack( + 'subnet create {subnet} -f json ' + '--network {net} ' + '--subnet-range 192.168.0.0/24 '.format( + subnet=self.SUBNET_NAME, + net=self.NET_NAME + )) + + self.openstack( + 'router add subnet {router} ' + '{subnet} '.format( + router=self.ROUTER_NAME, + subnet=self.SUBNET_NAME + ) + ) + + TestNatGateway.ROUTER_ID = router['id'] + TestNatGateway.NET_ID = net['id'] + + def _denitialize_network(self): + self.openstack( + 'router remove subnet {router} ' + '{subnet} '.format( + router=self.ROUTER_NAME, + subnet=self.SUBNET_NAME + ) + ) + self.openstack( + 'subnet delete ' + self.SUBNET_NAME + ) + self.openstack( + 'network delete ' + self.NET_NAME + ) + self.openstack( + 'router delete ' + self.ROUTER_NAME + ) diff --git a/otcextensions/tests/unit/osclient/nat/v2/test_gateway.py b/otcextensions/tests/unit/osclient/nat/v2/test_gateway.py index e5487d1c5..4dafce406 100644 --- a/otcextensions/tests/unit/osclient/nat/v2/test_gateway.py +++ b/otcextensions/tests/unit/osclient/nat/v2/test_gateway.py @@ -131,7 +131,7 @@ def setUp(self): self.cmd = gateway.ShowNatGateway(self.app, None) - self.client.get_gateway = mock.Mock(return_value=self._data) + self.client.find_gateway = mock.Mock(return_value=self._data) def test_show(self): arglist = [ @@ -147,7 +147,7 @@ def test_show(self): # Trigger the action columns, data = self.cmd.take_action(parsed_args) - self.client.get_gateway.assert_called_with('test_gateway') + self.client.find_gateway.assert_called_with('test_gateway') self.assertEqual(self.columns, columns) self.assertEqual(self.data, data) @@ -162,7 +162,7 @@ def setUp(self): self.cmd = gateway.DeleteNatGateway(self.app, None) - self.client.get_gateway = mock.Mock(return_value=self.data) + self.client.find_gateway = mock.Mock(return_value=self.data) self.client.delete_gateway = mock.Mock(return_value=self.data) def test_delete(self): @@ -180,6 +180,6 @@ def test_delete(self): # Trigger the action self.cmd.take_action(parsed_args) - self.client.get_gateway.assert_called_with('test_gateway') + self.client.find_gateway.assert_called_with('test_gateway') self.client.delete_gateway.assert_called_with(self.data.id) From 20189222f467611f94a804e7fcc0ae310a68e38e Mon Sep 17 00:00:00 2001 From: Vineet Pruthi Date: Wed, 29 Jan 2020 10:53:44 +0000 Subject: [PATCH 17/73] Adding osclient code for nat --- otcextensions/osclient/nat/v2/dnat.py | 61 +++----------- otcextensions/osclient/nat/v2/gateway.py | 58 +++++-------- otcextensions/osclient/nat/v2/snat.py | 72 +++++------------ .../tests/unit/osclient/nat/v2/fakes.py | 81 ++++++++++--------- .../unit/osclient/nat/v2/test_gateway.py | 69 ++++++++-------- 5 files changed, 122 insertions(+), 219 deletions(-) diff --git a/otcextensions/osclient/nat/v2/dnat.py b/otcextensions/osclient/nat/v2/dnat.py index 813fd860f..6e10ce625 100644 --- a/otcextensions/osclient/nat/v2/dnat.py +++ b/otcextensions/osclient/nat/v2/dnat.py @@ -17,29 +17,14 @@ from osc_lib.command import command from otcextensions.i18n import _ -from otcextensions.common import sdk_utils LOG = logging.getLogger(__name__) -def _get_columns(item): - column_map = { - } - return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map) - - class ListDnatRules(command.Lister): _description = _("List DNAT Rules.") - columns = ( - 'Id', - 'Nat Gateway Id', - 'Port Id', - 'Private IP', - 'Floating Ip Address', - 'Protocol', - 'Status' - ) + columns = ('Id', 'Nat Gateway Id', 'Port Id', 'Private IP', 'Floating Ip Address', 'Protocol', 'Status') def get_parser(self, prog_name): parser = super(ListDnatRules, self).get_parser(prog_name) @@ -51,12 +36,10 @@ def get_parser(self, prog_name): parser.add_argument( '--limit', metavar='', - type=int, help=_('Limit to fetch number of records.')) parser.add_argument( '--project-id', metavar='', - dest='tenant_id', help=_('Specifies the project ID.')) parser.add_argument( '--nat-gateway-id', @@ -69,13 +52,11 @@ def get_parser(self, prog_name): parser.add_argument( '--private-ip', metavar='', - help=_('Specifies the private IP address, for example, ' - 'the IP address of a Direct Connect connection.')) + help=_('Specifies the private IP address, for example,the IP address of a Direct Connect connection.')) parser.add_argument( '--internal-service-port', metavar='', - help=_('Specifies port used by ECSs or BMSs toprovide ' - 'services for external systems.')) + help=_('Specifies port used by ECSs or BMSs toprovide services for external systems.')) parser.add_argument( '--floating-ip-id', metavar='', @@ -112,27 +93,14 @@ def get_parser(self, prog_name): def take_action(self, parsed_args): client = self.app.client_manager.nat args_list = [ - 'id', - 'limit', - 'tenant_id', - 'nat_gateway_id', - 'port_id', - 'private_ip', - 'internal_service_port', - 'floating_ip_id', - 'floating_ip_address', - 'external_service_port', - 'protocol', - 'status', - 'admin_state_up', - 'created_at' + 'id', 'limit', 'tenant_id', 'nat_gateway_id', 'port_id', 'private_ip', 'internal_service_port', 'floating_ip_id', 'floating_ip_address', 'external_service_port', 'protocol', 'status', 'admin_state_up', 'created_at' ] attrs = {} for arg in args_list: if getattr(parsed_args, arg): attrs[arg] = getattr(parsed_args, arg) - data = client.dnat_rules(**attrs) + data = client.dnat_rules(**args) return ( self.columns, @@ -181,18 +149,15 @@ def get_parser(self, prog_name): parser.add_argument( '--private-ip', metavar='', - help=_('Specifies the private IP address, for example, ' - 'the IP address of a Direct Connect connection.')) + help=_('Specifies the private IP address, for example,the IP address of a Direct Connect connection.')) parser.add_argument( '--internal-service-port', metavar='', - help=_('Specifies port used by ECSs or BMSs toprovide ' - 'services for external systems.')) + help=_('Specifies port used by ECSs or BMSs toprovide services for external systems.')) parser.add_argument( 'floating_ip_id', metavar="", - help=_('Specifies the EIP ID. Multiple EIPs are ' - 'separated using commas')) + help=_("Specifies the EIP ID. Multiple EIPs are separated using commas")) parser.add_argument( '--external-service-port', metavar='', @@ -207,15 +172,7 @@ def get_parser(self, prog_name): def take_action(self, parsed_args): client = self.app.client_manager.nat - args_list = [ - 'nat_gateway_id', - 'port_id', - 'private_ip', - 'internal_service_port', - 'floating_ip_id', - 'external_service_port', - 'protocol' - ] + args_list = ['nat_gateway_id', 'port_id', 'private_ip', 'internal_service_port', 'floating_ip_id', 'external_service_port', 'protocol'] attrs = {} for arg in args_list: if getattr(parsed_args, arg): diff --git a/otcextensions/osclient/nat/v2/gateway.py b/otcextensions/osclient/nat/v2/gateway.py index 7db142c63..abc8a965b 100644 --- a/otcextensions/osclient/nat/v2/gateway.py +++ b/otcextensions/osclient/nat/v2/gateway.py @@ -17,24 +17,17 @@ from osc_lib.command import command from otcextensions.i18n import _ -from otcextensions.common import sdk_utils LOG = logging.getLogger(__name__) -def _get_columns(item): - column_map = { - } - return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map) - - -class ListNatGateways(command.Lister): +class ListNatGateway(command.Lister): _description = _("List Nat Gateway.") columns = ('Id', 'Name', 'Spec', 'Router Id', 'Status') def get_parser(self, prog_name): - parser = super(ListNatGateways, self).get_parser(prog_name) + parser = super(ListNatGateway, self).get_parser(prog_name) parser.add_argument( '--id', @@ -43,12 +36,10 @@ def get_parser(self, prog_name): parser.add_argument( '--limit', metavar='', - type=int, help=_('Limit to fetch number of records.')) parser.add_argument( '--project-id', metavar='', - dest='tenant_id', help=_('Specifies the project ID.')) parser.add_argument( '--name', @@ -73,8 +64,7 @@ def get_parser(self, prog_name): parser.add_argument( '--admin-state-up', metavar='', - help=_('Specifies whether the NAT Gateway is enabled ' - 'or disabled.')) + help=_('Specifies whether the NAT Gateway is enabled or disabled.')) parser.add_argument( '--created-at', metavar='', @@ -87,25 +77,22 @@ def get_parser(self, prog_name): def take_action(self, parsed_args): client = self.app.client_manager.nat args_list = [ - 'id', - 'limit', - 'tenant_id', - 'name', - 'spec', - 'router_id', - 'internal_network_id', - 'status', - 'admin_state_up', - 'created_at'] + 'id', 'limit', 'tenant_id', 'name', 'description', 'spec', 'router_id', 'internal_network_id', 'status', 'admin_state_up', 'created_at' + ] attrs = {} for arg in args_list: if getattr(parsed_args, arg): attrs[arg] = getattr(parsed_args, arg) - data = client.gateways(**attrs) + data = client.gateways(**args) - return (self.columns, (utils.get_item_properties(s, self.columns) - for s in data)) + return ( + self.columns, + (utils.get_item_properties( + s, + self.columns, + ) for s in data) + ) class ShowNatGateway(command.ShowOne): @@ -114,15 +101,15 @@ class ShowNatGateway(command.ShowOne): def get_parser(self, prog_name): parser = super(ShowNatGateway, self).get_parser(prog_name) parser.add_argument( - 'nat_gateway', - metavar='', + 'nat_gateway_id', + metavar='', help=_('Specifies the ID of the NAT Gateway.'), ) return parser def take_action(self, parsed_args): client = self.app.client_manager.nat - obj = client.find_gateway(parsed_args.nat_gateway) + obj = client.get_gateway(parsed_args.nat_gateway_id) display_columns, columns = _get_columns(obj) data = utils.get_item_properties(obj, columns) @@ -162,12 +149,7 @@ def get_parser(self, prog_name): def take_action(self, parsed_args): client = self.app.client_manager.nat - args_list = [ - 'name', - 'description', - 'spec', - 'router_id', - 'internal_network_id'] + args_list = ['name', 'description', 'spec', 'router_id', 'internal_network_id'] attrs = {} for arg in args_list: if getattr(parsed_args, arg): @@ -214,7 +196,7 @@ def take_action(self, parsed_args): for arg in args_list: if getattr(parsed_args, arg): attrs[arg] = getattr(parsed_args, arg) - nat_gateway = client.find_gateway(parsed_args.nat_gateway) + nat_gateway = client.get_gateway(parsed_args.nat_gateway) obj = client.update_gateway(nat_gateway.id, **attrs) @@ -240,5 +222,5 @@ def get_parser(self, prog_name): def take_action(self, parsed_args): client = self.app.client_manager.nat - nat_gateway = client.find_gateway(parsed_args.nat_gateway) - client.delete_gateway(nat_gateway.id) + nat_gateway = client.get_gateway(parsed_args.nat_gateway) + return client.delete_gateway(nat_gateway.id) diff --git a/otcextensions/osclient/nat/v2/snat.py b/otcextensions/osclient/nat/v2/snat.py index 4391769d5..c87100832 100644 --- a/otcextensions/osclient/nat/v2/snat.py +++ b/otcextensions/osclient/nat/v2/snat.py @@ -17,28 +17,14 @@ from osc_lib.command import command from otcextensions.i18n import _ -from otcextensions.common import sdk_utils LOG = logging.getLogger(__name__) -def _get_columns(item): - column_map = { - } - return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map) - - class ListSnatRules(command.Lister): _description = _("List SNAT Rules.") - columns = ( - 'Id', - 'Nat Gateway Id', - 'Network Id', - 'Cidr', - 'Floating Ip Address', - 'Status' - ) + columns = ('Id', 'Nat Gateway Id', 'Network Id', 'Cidr', 'Floating Ip Address', 'Status') def get_parser(self, prog_name): parser = super(ListSnatRules, self).get_parser(prog_name) @@ -50,26 +36,23 @@ def get_parser(self, prog_name): parser.add_argument( '--limit', metavar='', - type=int, help=_('Limit to fetch number of records.')) parser.add_argument( '--project-id', metavar='', - dest='tenant_id', help=_('Specifies the project ID.')) parser.add_argument( '--nat-gateway-id', metavar='', help=_('Specifies the NAT gateway ID.')) parser.add_argument( - '--network-id', + '--net-id', metavar='', help=_('Specifies the network ID used by theSNAT rule.')) parser.add_argument( '--cidr', metavar='', - help=_('Specifies a subset of the VPC subnetCIDR block or ' - 'a CIDR block of DirectConnect connection.')) + help=_('Specifies a subset of the VPC subnetCIDR block or a CIDR block of DirectConnect connection.')) parser.add_argument( '--source-type', metavar='', @@ -102,25 +85,14 @@ def get_parser(self, prog_name): def take_action(self, parsed_args): client = self.app.client_manager.nat args_list = [ - 'id', - 'limit', - 'network_id', - 'tenant_id', - 'nat_gateway_id', - 'network_id', - 'cidr', - 'source_type', - 'floating_ip_id', - 'floating_ip_address', - 'status', - 'admin_state_up', - 'created_at'] + 'id', 'limit', 'network_id', 'tenant_id', 'nat_gateway_id', 'network_id', 'cidr', 'source_type', 'floating_ip_id', 'floating_ip_address', 'status', 'admin_state_up', 'created_at' + ] attrs = {} for arg in args_list: if getattr(parsed_args, arg): attrs[arg] = getattr(parsed_args, arg) - data = client.snat_rules(**attrs) + data = client.snat_rules(**args) return ( self.columns, @@ -160,40 +132,31 @@ def get_parser(self, prog_name): parser = super(CreateSnatRule, self).get_parser(prog_name) parser.add_argument( 'nat_gateway_id', - metavar='', - help=_('Specifies the ID of the NAT gateway')) + metavar="", + help=_("Specifies the ID of the NAT gateway")) parser.add_argument( 'floating_ip_id', - metavar='', - help=_('Specifies the EIP ID. Multiple EIPs ' - 'are separated using commas')) + metavar="", + help=_("Specifies the EIP ID. Multiple EIPs are separated using commas")) parser.add_argument( '--net-id', - metavar='', - help=_('Specifies the network ID used by the SNAT rule. ' - 'This parameter and cidr arealternative.')) + metavar="", + help=_("Specifies the network ID used by the SNATrule. This parameter and cidr arealternative.")) parser.add_argument( '--cidr', - metavar='', - help=_('Specifies CIDR, which can be in the formatof a ' - 'network segment or a host IP address')) + metavar="", + help=_("Specifies CIDR, which can be in the formatof a network segment or a host IP address")) parser.add_argument( '--source-type', - metavar='', - help=_('Specifies the source type.')) + metavar="", + help=_("Specifies the source type.")) return parser def take_action(self, parsed_args): client = self.app.client_manager.nat - args_list = [ - 'nat_gateway_id', - 'floating_ip_id', - 'network_id', - 'cidr', - 'source_type' - ] + args_list = ['nat_gateway_id', 'floating_ip_id', 'network_id', 'cidr', 'source_type'] attrs = {} for arg in args_list: if getattr(parsed_args, arg): @@ -225,3 +188,4 @@ def take_action(self, parsed_args): client = self.app.client_manager.nat snat_rule = client.get_snat_rule(parsed_args.snat_rule_id) return client.delete_snat_rule(snat_rule.id) + diff --git a/otcextensions/tests/unit/osclient/nat/v2/fakes.py b/otcextensions/tests/unit/osclient/nat/v2/fakes.py index d746af427..215352d16 100644 --- a/otcextensions/tests/unit/osclient/nat/v2/fakes.py +++ b/otcextensions/tests/unit/osclient/nat/v2/fakes.py @@ -10,8 +10,8 @@ # License for the specific language governing permissions and limitations # under the License. # +import random import uuid -import time import mock @@ -38,7 +38,7 @@ def gen_data_dict(data, columns): class TestNat(utils.TestCommand): def setUp(self): - super(TestNat, self).setUp() + super(TestRds, self).setUp() self.app.client_manager.nat = mock.Mock() @@ -60,19 +60,21 @@ def generate(cls): """ # Set default attributes. object_info = { - "id": "id-" + uuid.uuid4().hex, - "name": "name-" + uuid.uuid4().hex, - "router_id": "router-" + uuid.uuid4().hex, - "status": "PENDING_CREATE", - "description": "my nat gateway", - "admin_state_up": 'true', - "tenant_id": "tenant-id-" + uuid.uuid4().hex, - "created_at": time.clock() * 1000, - "spec": "1", - "internal_network_id": "net-id-" + uuid.uuid4().hex + "nat_gateway": { + "id": "id-" + uuid.uuid4().hex, + "name": "name-" + uuid.uuid4().hex, + "router_id": "router-" + uuid.uuid4().hex, + "status": "PENDING_CREATE", + "description": "my nat gateway", + "admin_state_up": true, + "tenant_id": "tenant-id-" + uuid.uuid4().hex, + "created_at": time.clock() * 1000, + "spec": "1", + "internal_network_id": "net-id-" + uuid.uuid4().hex + } } - return gateway.Gateway(**object_info) + return datastore.Datastore(**object_info) class FakeSnatRule(test_base.Fake): @@ -87,18 +89,20 @@ def generate(cls): # Set default attributes. object_info = { - "id": "id-" + uuid.uuid4().hex, - "floating_ip_id": "eip-id-" + uuid.uuid4().hex, - "status": "PENDING_CREATE", - "nat_gateway_id": "gw-id-" + uuid.uuid4().hex, - "admin_state_up": True, - "network_id": "net-id-" + uuid.uuid4().hex, - "cidr": uuid.uuid4().hex, - "source_type": 0, - "tenant_id": "tenant-id-" + uuid.uuid4().hex, - "created_at": time.clock() * 1000, - "floating_ip_address": uuid.uuid4().hex - } + "snat_rule": { + "id": "id-", + "floating_ip_id": "eip-id-" + uuid.uuid4().hex, + "status": "PENDING_CREATE", + "nat_gateway_id": "gw-id-" + uuid.uuid4().hex, + "admin_state_up": true, + "network_id": "net-id-" + uuid.uuid4().hex, + "cidr": null, + "source_type":0, + "tenant_id": "tenant-id-" + uuid.uuid4().hex, + "created_at": time.clock() * 1000, + "floating_ip_address": uuid.uuid4().hex + } + } return snat.Snat.existing(**object_info) @@ -108,19 +112,20 @@ class FakeDnatRule(test_base.Fake): @classmethod def generate(cls): object_info = { - "id": "id-" + uuid.uuid4().hex, - "floating_ip_id": "eip-id-" + uuid.uuid4().hex, - "status": "ACTIVE", - "nat_gateway_id": "gw-id-" + uuid.uuid4().hex, - "admin_state_up": True, - "private_ip": uuid.uuid4().hex, - "internal_service_port": 0, - "protocol": "any", - "tenant_id": "abc", - "port_id": "", - "created_at": time.clock() * 1000, - "floating_ip_address": uuid.uuid4().hex, - "external_service_port": 0 + "dnat_rule": { + "id": "id-", + "floating_ip_id": "eip-id-" + uuid.uuid4().hex, + "status": "ACTIVE", + "nat_gateway_id": "gw-id-" + uuid.uuid4().hex, + "admin_state_up": true, + "private_ip": uuid.uuid4().hex, + "internal_service_port": 0, + "protocol": "any", + "tenant_id": "abc", + "created_at": time.clock() * 1000, + "floating_ip_address": uuid.uuid4().hex, + "external_service_port": 0 + } } obj = dnat.Dnat.existing(**object_info) diff --git a/otcextensions/tests/unit/osclient/nat/v2/test_gateway.py b/otcextensions/tests/unit/osclient/nat/v2/test_gateway.py index 4dafce406..ef9821551 100644 --- a/otcextensions/tests/unit/osclient/nat/v2/test_gateway.py +++ b/otcextensions/tests/unit/osclient/nat/v2/test_gateway.py @@ -12,6 +12,8 @@ # import mock +from osc_lib import exceptions + from otcextensions.osclient.nat.v2 import gateway from otcextensions.tests.unit.osclient.nat.v2 import fakes @@ -20,15 +22,19 @@ class TestListNatGateways(fakes.TestNat): objects = fakes.FakeNatGateway.create_multiple(3) - column_list_headers = ('Id', 'Name', 'Spec', 'Router Id', 'Status') + column_list_headers = ( + 'Id', 'Name', 'Router Id', 'Status', 'description', 'admin state up', 'Tenant Id', 'Spec', 'Created at' + ) - columns = ('id', 'name', 'spec', 'router_id', 'status') + columns = ( + 'Id', 'Name', 'Spec', 'Router Id', 'Status' + ) data = [] for s in objects: data.append( - (s.id, s.name, s.spec, s.router_id, s.status)) + (s.id, s.name, s.souter_id, s.status, s.description, s.admin_state_up, s.tenant_id, s.spec, s.created_at)) def setUp(self): super(TestListNatGateways, self).setUp() @@ -62,48 +68,45 @@ def test_list_args(self): '--limit', '1', '--id', '2', '--name', '3', - '--project-id', '4', - '--spec', '5', + '--tenant-id', 'abc', + '--description', 'test', + '--spec', '1', '--router-id', '6', '--internal-network-id', '7', - '--admin-state-up', '8', - '--created-at', '9', - '--status', '10' + '--admin-state-up', 'true', + '--created-at', '20', ] verifylist = [ ('limit', 1), ('id', '2'), ('name', '3'), - ('tenant_id', '4'), - ('spec', '5'), + ('project_id', 'abc'), + ('description', 'test'), + ('spec', '1'), ('router_id', '6'), ('internal_network_id', '7'), - ('admin_state_up', '8'), - ('created_at', '9'), - ('status', '10'), + ('admin_state_up', 'true'), + ('created_at', '20'), ] # Verify cm is triggered with default parameters parsed_args = self.check_parser(self.cmd, arglist, verifylist) - # Set the response - self.client.api_mock.side_effect = [self.objects] - # Trigger the action columns, data = self.cmd.take_action(parsed_args) self.client.api_mock.assert_called_with( - limit=1, + limit='1', id='2', name='3', - tenant_id='4', - spec='5', + project_id='abc', + description=test, + spec='1', router_id='6', internal_network_id='7', - admin_state_up='8', - created_at='9', - status='10', + admin_state_up='true', + created_at='20' ) @@ -112,16 +115,7 @@ class TestShowNatGateway(fakes.TestNat): _data = fakes.FakeNatGateway.create_one() columns = ( - 'admin_state_up', - 'created_at', - 'description', - 'id', - 'internal_network_id', - 'name', - 'project_id', - 'router_id', - 'spec', - 'status' + 'id', 'name', 'internal network id', 'spec', 'router id', 'tenant id', 'status', 'description', 'admin state up' ) data = fakes.gen_data(_data, columns) @@ -131,7 +125,7 @@ def setUp(self): self.cmd = gateway.ShowNatGateway(self.app, None) - self.client.find_gateway = mock.Mock(return_value=self._data) + self.client.get_gateway = mock.Mock(return_value=self._data) def test_show(self): arglist = [ @@ -139,7 +133,7 @@ def test_show(self): ] verifylist = [ - ('nat_gateway', 'test_gateway'), + ('gateway', 'test_gateway'), ] # Verify cm is triggered with default parameters @@ -147,7 +141,8 @@ def test_show(self): # Trigger the action columns, data = self.cmd.take_action(parsed_args) - self.client.find_gateway.assert_called_with('test_gateway') + self.client.get_gateway.assert_called_with('test_gateway', + ignore_missing=False) self.assertEqual(self.columns, columns) self.assertEqual(self.data, data) @@ -162,7 +157,7 @@ def setUp(self): self.cmd = gateway.DeleteNatGateway(self.app, None) - self.client.find_gateway = mock.Mock(return_value=self.data) + self.client.get_gateway = mock.Mock(return_value=self.data) self.client.delete_gateway = mock.Mock(return_value=self.data) def test_delete(self): @@ -180,6 +175,6 @@ def test_delete(self): # Trigger the action self.cmd.take_action(parsed_args) - self.client.find_gateway.assert_called_with('test_gateway') + self.client.get_gateway.assert_called_with('nat_gateway_id_or_name') self.client.delete_gateway.assert_called_with(self.data.id) From 2b5caf0a48935425ffc908686f1f4fdb83f0c0f6 Mon Sep 17 00:00:00 2001 From: Vineet Pruthi Date: Mon, 3 Feb 2020 04:29:05 +0000 Subject: [PATCH 18/73] Fixed error and adding unit tests for osclient --- otcextensions/osclient/nat/v2/dnat.py | 61 +++++++++++--- otcextensions/osclient/nat/v2/gateway.py | 52 ++++++++---- otcextensions/osclient/nat/v2/snat.py | 72 ++++++++++++----- .../tests/unit/osclient/nat/v2/fakes.py | 81 +++++++++---------- .../unit/osclient/nat/v2/test_gateway.py | 65 ++++++++------- .../tests/unit/osclient/nat/v2/test_snat.py | 4 +- 6 files changed, 216 insertions(+), 119 deletions(-) diff --git a/otcextensions/osclient/nat/v2/dnat.py b/otcextensions/osclient/nat/v2/dnat.py index 6e10ce625..813fd860f 100644 --- a/otcextensions/osclient/nat/v2/dnat.py +++ b/otcextensions/osclient/nat/v2/dnat.py @@ -17,14 +17,29 @@ from osc_lib.command import command from otcextensions.i18n import _ +from otcextensions.common import sdk_utils LOG = logging.getLogger(__name__) +def _get_columns(item): + column_map = { + } + return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map) + + class ListDnatRules(command.Lister): _description = _("List DNAT Rules.") - columns = ('Id', 'Nat Gateway Id', 'Port Id', 'Private IP', 'Floating Ip Address', 'Protocol', 'Status') + columns = ( + 'Id', + 'Nat Gateway Id', + 'Port Id', + 'Private IP', + 'Floating Ip Address', + 'Protocol', + 'Status' + ) def get_parser(self, prog_name): parser = super(ListDnatRules, self).get_parser(prog_name) @@ -36,10 +51,12 @@ def get_parser(self, prog_name): parser.add_argument( '--limit', metavar='', + type=int, help=_('Limit to fetch number of records.')) parser.add_argument( '--project-id', metavar='', + dest='tenant_id', help=_('Specifies the project ID.')) parser.add_argument( '--nat-gateway-id', @@ -52,11 +69,13 @@ def get_parser(self, prog_name): parser.add_argument( '--private-ip', metavar='', - help=_('Specifies the private IP address, for example,the IP address of a Direct Connect connection.')) + help=_('Specifies the private IP address, for example, ' + 'the IP address of a Direct Connect connection.')) parser.add_argument( '--internal-service-port', metavar='', - help=_('Specifies port used by ECSs or BMSs toprovide services for external systems.')) + help=_('Specifies port used by ECSs or BMSs toprovide ' + 'services for external systems.')) parser.add_argument( '--floating-ip-id', metavar='', @@ -93,14 +112,27 @@ def get_parser(self, prog_name): def take_action(self, parsed_args): client = self.app.client_manager.nat args_list = [ - 'id', 'limit', 'tenant_id', 'nat_gateway_id', 'port_id', 'private_ip', 'internal_service_port', 'floating_ip_id', 'floating_ip_address', 'external_service_port', 'protocol', 'status', 'admin_state_up', 'created_at' + 'id', + 'limit', + 'tenant_id', + 'nat_gateway_id', + 'port_id', + 'private_ip', + 'internal_service_port', + 'floating_ip_id', + 'floating_ip_address', + 'external_service_port', + 'protocol', + 'status', + 'admin_state_up', + 'created_at' ] attrs = {} for arg in args_list: if getattr(parsed_args, arg): attrs[arg] = getattr(parsed_args, arg) - data = client.dnat_rules(**args) + data = client.dnat_rules(**attrs) return ( self.columns, @@ -149,15 +181,18 @@ def get_parser(self, prog_name): parser.add_argument( '--private-ip', metavar='', - help=_('Specifies the private IP address, for example,the IP address of a Direct Connect connection.')) + help=_('Specifies the private IP address, for example, ' + 'the IP address of a Direct Connect connection.')) parser.add_argument( '--internal-service-port', metavar='', - help=_('Specifies port used by ECSs or BMSs toprovide services for external systems.')) + help=_('Specifies port used by ECSs or BMSs toprovide ' + 'services for external systems.')) parser.add_argument( 'floating_ip_id', metavar="", - help=_("Specifies the EIP ID. Multiple EIPs are separated using commas")) + help=_('Specifies the EIP ID. Multiple EIPs are ' + 'separated using commas')) parser.add_argument( '--external-service-port', metavar='', @@ -172,7 +207,15 @@ def get_parser(self, prog_name): def take_action(self, parsed_args): client = self.app.client_manager.nat - args_list = ['nat_gateway_id', 'port_id', 'private_ip', 'internal_service_port', 'floating_ip_id', 'external_service_port', 'protocol'] + args_list = [ + 'nat_gateway_id', + 'port_id', + 'private_ip', + 'internal_service_port', + 'floating_ip_id', + 'external_service_port', + 'protocol' + ] attrs = {} for arg in args_list: if getattr(parsed_args, arg): diff --git a/otcextensions/osclient/nat/v2/gateway.py b/otcextensions/osclient/nat/v2/gateway.py index abc8a965b..14bfd14cb 100644 --- a/otcextensions/osclient/nat/v2/gateway.py +++ b/otcextensions/osclient/nat/v2/gateway.py @@ -17,17 +17,24 @@ from osc_lib.command import command from otcextensions.i18n import _ +from otcextensions.common import sdk_utils LOG = logging.getLogger(__name__) -class ListNatGateway(command.Lister): +def _get_columns(item): + column_map = { + } + return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map) + + +class ListNatGateways(command.Lister): _description = _("List Nat Gateway.") columns = ('Id', 'Name', 'Spec', 'Router Id', 'Status') def get_parser(self, prog_name): - parser = super(ListNatGateway, self).get_parser(prog_name) + parser = super(ListNatGateways, self).get_parser(prog_name) parser.add_argument( '--id', @@ -36,10 +43,12 @@ def get_parser(self, prog_name): parser.add_argument( '--limit', metavar='', + type=int, help=_('Limit to fetch number of records.')) parser.add_argument( '--project-id', metavar='', + dest='tenant_id', help=_('Specifies the project ID.')) parser.add_argument( '--name', @@ -64,7 +73,8 @@ def get_parser(self, prog_name): parser.add_argument( '--admin-state-up', metavar='', - help=_('Specifies whether the NAT Gateway is enabled or disabled.')) + help=_('Specifies whether the NAT Gateway is enabled ' + 'or disabled.')) parser.add_argument( '--created-at', metavar='', @@ -77,22 +87,25 @@ def get_parser(self, prog_name): def take_action(self, parsed_args): client = self.app.client_manager.nat args_list = [ - 'id', 'limit', 'tenant_id', 'name', 'description', 'spec', 'router_id', 'internal_network_id', 'status', 'admin_state_up', 'created_at' - ] + 'id', + 'limit', + 'tenant_id', + 'name', + 'spec', + 'router_id', + 'internal_network_id', + 'status', + 'admin_state_up', + 'created_at'] attrs = {} for arg in args_list: if getattr(parsed_args, arg): attrs[arg] = getattr(parsed_args, arg) - data = client.gateways(**args) + data = client.gateways(**attrs) - return ( - self.columns, - (utils.get_item_properties( - s, - self.columns, - ) for s in data) - ) + return (self.columns, (utils.get_item_properties(s, self.columns) + for s in data)) class ShowNatGateway(command.ShowOne): @@ -101,15 +114,15 @@ class ShowNatGateway(command.ShowOne): def get_parser(self, prog_name): parser = super(ShowNatGateway, self).get_parser(prog_name) parser.add_argument( - 'nat_gateway_id', - metavar='', + 'nat_gateway', + metavar='', help=_('Specifies the ID of the NAT Gateway.'), ) return parser def take_action(self, parsed_args): client = self.app.client_manager.nat - obj = client.get_gateway(parsed_args.nat_gateway_id) + obj = client.get_gateway(parsed_args.nat_gateway) display_columns, columns = _get_columns(obj) data = utils.get_item_properties(obj, columns) @@ -149,7 +162,12 @@ def get_parser(self, prog_name): def take_action(self, parsed_args): client = self.app.client_manager.nat - args_list = ['name', 'description', 'spec', 'router_id', 'internal_network_id'] + args_list = [ + 'name', + 'description', + 'spec', + 'router_id', + 'internal_network_id'] attrs = {} for arg in args_list: if getattr(parsed_args, arg): diff --git a/otcextensions/osclient/nat/v2/snat.py b/otcextensions/osclient/nat/v2/snat.py index c87100832..4391769d5 100644 --- a/otcextensions/osclient/nat/v2/snat.py +++ b/otcextensions/osclient/nat/v2/snat.py @@ -17,14 +17,28 @@ from osc_lib.command import command from otcextensions.i18n import _ +from otcextensions.common import sdk_utils LOG = logging.getLogger(__name__) +def _get_columns(item): + column_map = { + } + return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map) + + class ListSnatRules(command.Lister): _description = _("List SNAT Rules.") - columns = ('Id', 'Nat Gateway Id', 'Network Id', 'Cidr', 'Floating Ip Address', 'Status') + columns = ( + 'Id', + 'Nat Gateway Id', + 'Network Id', + 'Cidr', + 'Floating Ip Address', + 'Status' + ) def get_parser(self, prog_name): parser = super(ListSnatRules, self).get_parser(prog_name) @@ -36,23 +50,26 @@ def get_parser(self, prog_name): parser.add_argument( '--limit', metavar='', + type=int, help=_('Limit to fetch number of records.')) parser.add_argument( '--project-id', metavar='', + dest='tenant_id', help=_('Specifies the project ID.')) parser.add_argument( '--nat-gateway-id', metavar='', help=_('Specifies the NAT gateway ID.')) parser.add_argument( - '--net-id', + '--network-id', metavar='', help=_('Specifies the network ID used by theSNAT rule.')) parser.add_argument( '--cidr', metavar='', - help=_('Specifies a subset of the VPC subnetCIDR block or a CIDR block of DirectConnect connection.')) + help=_('Specifies a subset of the VPC subnetCIDR block or ' + 'a CIDR block of DirectConnect connection.')) parser.add_argument( '--source-type', metavar='', @@ -85,14 +102,25 @@ def get_parser(self, prog_name): def take_action(self, parsed_args): client = self.app.client_manager.nat args_list = [ - 'id', 'limit', 'network_id', 'tenant_id', 'nat_gateway_id', 'network_id', 'cidr', 'source_type', 'floating_ip_id', 'floating_ip_address', 'status', 'admin_state_up', 'created_at' - ] + 'id', + 'limit', + 'network_id', + 'tenant_id', + 'nat_gateway_id', + 'network_id', + 'cidr', + 'source_type', + 'floating_ip_id', + 'floating_ip_address', + 'status', + 'admin_state_up', + 'created_at'] attrs = {} for arg in args_list: if getattr(parsed_args, arg): attrs[arg] = getattr(parsed_args, arg) - data = client.snat_rules(**args) + data = client.snat_rules(**attrs) return ( self.columns, @@ -132,31 +160,40 @@ def get_parser(self, prog_name): parser = super(CreateSnatRule, self).get_parser(prog_name) parser.add_argument( 'nat_gateway_id', - metavar="", - help=_("Specifies the ID of the NAT gateway")) + metavar='', + help=_('Specifies the ID of the NAT gateway')) parser.add_argument( 'floating_ip_id', - metavar="", - help=_("Specifies the EIP ID. Multiple EIPs are separated using commas")) + metavar='', + help=_('Specifies the EIP ID. Multiple EIPs ' + 'are separated using commas')) parser.add_argument( '--net-id', - metavar="", - help=_("Specifies the network ID used by the SNATrule. This parameter and cidr arealternative.")) + metavar='', + help=_('Specifies the network ID used by the SNAT rule. ' + 'This parameter and cidr arealternative.')) parser.add_argument( '--cidr', - metavar="", - help=_("Specifies CIDR, which can be in the formatof a network segment or a host IP address")) + metavar='', + help=_('Specifies CIDR, which can be in the formatof a ' + 'network segment or a host IP address')) parser.add_argument( '--source-type', - metavar="", - help=_("Specifies the source type.")) + metavar='', + help=_('Specifies the source type.')) return parser def take_action(self, parsed_args): client = self.app.client_manager.nat - args_list = ['nat_gateway_id', 'floating_ip_id', 'network_id', 'cidr', 'source_type'] + args_list = [ + 'nat_gateway_id', + 'floating_ip_id', + 'network_id', + 'cidr', + 'source_type' + ] attrs = {} for arg in args_list: if getattr(parsed_args, arg): @@ -188,4 +225,3 @@ def take_action(self, parsed_args): client = self.app.client_manager.nat snat_rule = client.get_snat_rule(parsed_args.snat_rule_id) return client.delete_snat_rule(snat_rule.id) - diff --git a/otcextensions/tests/unit/osclient/nat/v2/fakes.py b/otcextensions/tests/unit/osclient/nat/v2/fakes.py index 215352d16..d746af427 100644 --- a/otcextensions/tests/unit/osclient/nat/v2/fakes.py +++ b/otcextensions/tests/unit/osclient/nat/v2/fakes.py @@ -10,8 +10,8 @@ # License for the specific language governing permissions and limitations # under the License. # -import random import uuid +import time import mock @@ -38,7 +38,7 @@ def gen_data_dict(data, columns): class TestNat(utils.TestCommand): def setUp(self): - super(TestRds, self).setUp() + super(TestNat, self).setUp() self.app.client_manager.nat = mock.Mock() @@ -60,21 +60,19 @@ def generate(cls): """ # Set default attributes. object_info = { - "nat_gateway": { - "id": "id-" + uuid.uuid4().hex, - "name": "name-" + uuid.uuid4().hex, - "router_id": "router-" + uuid.uuid4().hex, - "status": "PENDING_CREATE", - "description": "my nat gateway", - "admin_state_up": true, - "tenant_id": "tenant-id-" + uuid.uuid4().hex, - "created_at": time.clock() * 1000, - "spec": "1", - "internal_network_id": "net-id-" + uuid.uuid4().hex - } + "id": "id-" + uuid.uuid4().hex, + "name": "name-" + uuid.uuid4().hex, + "router_id": "router-" + uuid.uuid4().hex, + "status": "PENDING_CREATE", + "description": "my nat gateway", + "admin_state_up": 'true', + "tenant_id": "tenant-id-" + uuid.uuid4().hex, + "created_at": time.clock() * 1000, + "spec": "1", + "internal_network_id": "net-id-" + uuid.uuid4().hex } - return datastore.Datastore(**object_info) + return gateway.Gateway(**object_info) class FakeSnatRule(test_base.Fake): @@ -89,20 +87,18 @@ def generate(cls): # Set default attributes. object_info = { - "snat_rule": { - "id": "id-", - "floating_ip_id": "eip-id-" + uuid.uuid4().hex, - "status": "PENDING_CREATE", - "nat_gateway_id": "gw-id-" + uuid.uuid4().hex, - "admin_state_up": true, - "network_id": "net-id-" + uuid.uuid4().hex, - "cidr": null, - "source_type":0, - "tenant_id": "tenant-id-" + uuid.uuid4().hex, - "created_at": time.clock() * 1000, - "floating_ip_address": uuid.uuid4().hex - } - } + "id": "id-" + uuid.uuid4().hex, + "floating_ip_id": "eip-id-" + uuid.uuid4().hex, + "status": "PENDING_CREATE", + "nat_gateway_id": "gw-id-" + uuid.uuid4().hex, + "admin_state_up": True, + "network_id": "net-id-" + uuid.uuid4().hex, + "cidr": uuid.uuid4().hex, + "source_type": 0, + "tenant_id": "tenant-id-" + uuid.uuid4().hex, + "created_at": time.clock() * 1000, + "floating_ip_address": uuid.uuid4().hex + } return snat.Snat.existing(**object_info) @@ -112,20 +108,19 @@ class FakeDnatRule(test_base.Fake): @classmethod def generate(cls): object_info = { - "dnat_rule": { - "id": "id-", - "floating_ip_id": "eip-id-" + uuid.uuid4().hex, - "status": "ACTIVE", - "nat_gateway_id": "gw-id-" + uuid.uuid4().hex, - "admin_state_up": true, - "private_ip": uuid.uuid4().hex, - "internal_service_port": 0, - "protocol": "any", - "tenant_id": "abc", - "created_at": time.clock() * 1000, - "floating_ip_address": uuid.uuid4().hex, - "external_service_port": 0 - } + "id": "id-" + uuid.uuid4().hex, + "floating_ip_id": "eip-id-" + uuid.uuid4().hex, + "status": "ACTIVE", + "nat_gateway_id": "gw-id-" + uuid.uuid4().hex, + "admin_state_up": True, + "private_ip": uuid.uuid4().hex, + "internal_service_port": 0, + "protocol": "any", + "tenant_id": "abc", + "port_id": "", + "created_at": time.clock() * 1000, + "floating_ip_address": uuid.uuid4().hex, + "external_service_port": 0 } obj = dnat.Dnat.existing(**object_info) diff --git a/otcextensions/tests/unit/osclient/nat/v2/test_gateway.py b/otcextensions/tests/unit/osclient/nat/v2/test_gateway.py index ef9821551..e5487d1c5 100644 --- a/otcextensions/tests/unit/osclient/nat/v2/test_gateway.py +++ b/otcextensions/tests/unit/osclient/nat/v2/test_gateway.py @@ -12,8 +12,6 @@ # import mock -from osc_lib import exceptions - from otcextensions.osclient.nat.v2 import gateway from otcextensions.tests.unit.osclient.nat.v2 import fakes @@ -22,19 +20,15 @@ class TestListNatGateways(fakes.TestNat): objects = fakes.FakeNatGateway.create_multiple(3) - column_list_headers = ( - 'Id', 'Name', 'Router Id', 'Status', 'description', 'admin state up', 'Tenant Id', 'Spec', 'Created at' - ) + column_list_headers = ('Id', 'Name', 'Spec', 'Router Id', 'Status') - columns = ( - 'Id', 'Name', 'Spec', 'Router Id', 'Status' - ) + columns = ('id', 'name', 'spec', 'router_id', 'status') data = [] for s in objects: data.append( - (s.id, s.name, s.souter_id, s.status, s.description, s.admin_state_up, s.tenant_id, s.spec, s.created_at)) + (s.id, s.name, s.spec, s.router_id, s.status)) def setUp(self): super(TestListNatGateways, self).setUp() @@ -68,45 +62,48 @@ def test_list_args(self): '--limit', '1', '--id', '2', '--name', '3', - '--tenant-id', 'abc', - '--description', 'test', - '--spec', '1', + '--project-id', '4', + '--spec', '5', '--router-id', '6', '--internal-network-id', '7', - '--admin-state-up', 'true', - '--created-at', '20', + '--admin-state-up', '8', + '--created-at', '9', + '--status', '10' ] verifylist = [ ('limit', 1), ('id', '2'), ('name', '3'), - ('project_id', 'abc'), - ('description', 'test'), - ('spec', '1'), + ('tenant_id', '4'), + ('spec', '5'), ('router_id', '6'), ('internal_network_id', '7'), - ('admin_state_up', 'true'), - ('created_at', '20'), + ('admin_state_up', '8'), + ('created_at', '9'), + ('status', '10'), ] # Verify cm is triggered with default parameters parsed_args = self.check_parser(self.cmd, arglist, verifylist) + # Set the response + self.client.api_mock.side_effect = [self.objects] + # Trigger the action columns, data = self.cmd.take_action(parsed_args) self.client.api_mock.assert_called_with( - limit='1', + limit=1, id='2', name='3', - project_id='abc', - description=test, - spec='1', + tenant_id='4', + spec='5', router_id='6', internal_network_id='7', - admin_state_up='true', - created_at='20' + admin_state_up='8', + created_at='9', + status='10', ) @@ -115,7 +112,16 @@ class TestShowNatGateway(fakes.TestNat): _data = fakes.FakeNatGateway.create_one() columns = ( - 'id', 'name', 'internal network id', 'spec', 'router id', 'tenant id', 'status', 'description', 'admin state up' + 'admin_state_up', + 'created_at', + 'description', + 'id', + 'internal_network_id', + 'name', + 'project_id', + 'router_id', + 'spec', + 'status' ) data = fakes.gen_data(_data, columns) @@ -133,7 +139,7 @@ def test_show(self): ] verifylist = [ - ('gateway', 'test_gateway'), + ('nat_gateway', 'test_gateway'), ] # Verify cm is triggered with default parameters @@ -141,8 +147,7 @@ def test_show(self): # Trigger the action columns, data = self.cmd.take_action(parsed_args) - self.client.get_gateway.assert_called_with('test_gateway', - ignore_missing=False) + self.client.get_gateway.assert_called_with('test_gateway') self.assertEqual(self.columns, columns) self.assertEqual(self.data, data) @@ -175,6 +180,6 @@ def test_delete(self): # Trigger the action self.cmd.take_action(parsed_args) - self.client.get_gateway.assert_called_with('nat_gateway_id_or_name') + self.client.get_gateway.assert_called_with('test_gateway') self.client.delete_gateway.assert_called_with(self.data.id) diff --git a/otcextensions/tests/unit/osclient/nat/v2/test_snat.py b/otcextensions/tests/unit/osclient/nat/v2/test_snat.py index a9b739b8d..c160e3f54 100644 --- a/otcextensions/tests/unit/osclient/nat/v2/test_snat.py +++ b/otcextensions/tests/unit/osclient/nat/v2/test_snat.py @@ -40,14 +40,14 @@ class TestListSnatRules(fakes.TestNat): data = [] for s in objects: - data.append(( + data.append( s.id, s.nat_gateway_id, s.network_id, s.cidr, s.floating_ip_address, s.status - )) + ) def setUp(self): super(TestListSnatRules, self).setUp() From 8e66a41654de46d967e533a661357b045cb00b13 Mon Sep 17 00:00:00 2001 From: Vineet Pruthi Date: Tue, 4 Feb 2020 01:09:45 +0000 Subject: [PATCH 19/73] Minor fix in unit test --- otcextensions/tests/unit/osclient/nat/v2/test_snat.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/otcextensions/tests/unit/osclient/nat/v2/test_snat.py b/otcextensions/tests/unit/osclient/nat/v2/test_snat.py index c160e3f54..a9b739b8d 100644 --- a/otcextensions/tests/unit/osclient/nat/v2/test_snat.py +++ b/otcextensions/tests/unit/osclient/nat/v2/test_snat.py @@ -40,14 +40,14 @@ class TestListSnatRules(fakes.TestNat): data = [] for s in objects: - data.append( + data.append(( s.id, s.nat_gateway_id, s.network_id, s.cidr, s.floating_ip_address, s.status - ) + )) def setUp(self): super(TestListSnatRules, self).setUp() From fa566675c97ce5b2c365b3873c40cef60103fe7e Mon Sep 17 00:00:00 2001 From: Vineet Pruthi Date: Wed, 19 Feb 2020 11:11:22 +0000 Subject: [PATCH 20/73] Adding functional tests for nat_gateway --- otcextensions/osclient/nat/v2/gateway.py | 8 ++++---- otcextensions/tests/unit/osclient/nat/v2/test_gateway.py | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/otcextensions/osclient/nat/v2/gateway.py b/otcextensions/osclient/nat/v2/gateway.py index 14bfd14cb..7db142c63 100644 --- a/otcextensions/osclient/nat/v2/gateway.py +++ b/otcextensions/osclient/nat/v2/gateway.py @@ -122,7 +122,7 @@ def get_parser(self, prog_name): def take_action(self, parsed_args): client = self.app.client_manager.nat - obj = client.get_gateway(parsed_args.nat_gateway) + obj = client.find_gateway(parsed_args.nat_gateway) display_columns, columns = _get_columns(obj) data = utils.get_item_properties(obj, columns) @@ -214,7 +214,7 @@ def take_action(self, parsed_args): for arg in args_list: if getattr(parsed_args, arg): attrs[arg] = getattr(parsed_args, arg) - nat_gateway = client.get_gateway(parsed_args.nat_gateway) + nat_gateway = client.find_gateway(parsed_args.nat_gateway) obj = client.update_gateway(nat_gateway.id, **attrs) @@ -240,5 +240,5 @@ def get_parser(self, prog_name): def take_action(self, parsed_args): client = self.app.client_manager.nat - nat_gateway = client.get_gateway(parsed_args.nat_gateway) - return client.delete_gateway(nat_gateway.id) + nat_gateway = client.find_gateway(parsed_args.nat_gateway) + client.delete_gateway(nat_gateway.id) diff --git a/otcextensions/tests/unit/osclient/nat/v2/test_gateway.py b/otcextensions/tests/unit/osclient/nat/v2/test_gateway.py index e5487d1c5..4dafce406 100644 --- a/otcextensions/tests/unit/osclient/nat/v2/test_gateway.py +++ b/otcextensions/tests/unit/osclient/nat/v2/test_gateway.py @@ -131,7 +131,7 @@ def setUp(self): self.cmd = gateway.ShowNatGateway(self.app, None) - self.client.get_gateway = mock.Mock(return_value=self._data) + self.client.find_gateway = mock.Mock(return_value=self._data) def test_show(self): arglist = [ @@ -147,7 +147,7 @@ def test_show(self): # Trigger the action columns, data = self.cmd.take_action(parsed_args) - self.client.get_gateway.assert_called_with('test_gateway') + self.client.find_gateway.assert_called_with('test_gateway') self.assertEqual(self.columns, columns) self.assertEqual(self.data, data) @@ -162,7 +162,7 @@ def setUp(self): self.cmd = gateway.DeleteNatGateway(self.app, None) - self.client.get_gateway = mock.Mock(return_value=self.data) + self.client.find_gateway = mock.Mock(return_value=self.data) self.client.delete_gateway = mock.Mock(return_value=self.data) def test_delete(self): @@ -180,6 +180,6 @@ def test_delete(self): # Trigger the action self.cmd.take_action(parsed_args) - self.client.get_gateway.assert_called_with('test_gateway') + self.client.find_gateway.assert_called_with('test_gateway') self.client.delete_gateway.assert_called_with(self.data.id) From 4a00fcb1d136aa2a07e7674f822385a7c9f20983 Mon Sep 17 00:00:00 2001 From: Vineet Pruthi Date: Wed, 11 Mar 2020 03:27:04 +0000 Subject: [PATCH 21/73] Adding some more functional tests for nat --- otcextensions/osclient/nat/v2/dnat.py | 3 +- otcextensions/osclient/nat/v2/snat.py | 3 +- otcextensions/sdk/nat/v2/dnat.py | 138 ++++++------- .../osclient/nat/v2/test_dnat_rule.py | 181 ++++++++++++++++++ .../osclient/nat/v2/test_snat_rule.py | 181 ++++++++++++++++++ 5 files changed, 434 insertions(+), 72 deletions(-) create mode 100644 otcextensions/tests/functional/osclient/nat/v2/test_dnat_rule.py create mode 100644 otcextensions/tests/functional/osclient/nat/v2/test_snat_rule.py diff --git a/otcextensions/osclient/nat/v2/dnat.py b/otcextensions/osclient/nat/v2/dnat.py index 813fd860f..983b07aa6 100644 --- a/otcextensions/osclient/nat/v2/dnat.py +++ b/otcextensions/osclient/nat/v2/dnat.py @@ -131,7 +131,6 @@ def take_action(self, parsed_args): for arg in args_list: if getattr(parsed_args, arg): attrs[arg] = getattr(parsed_args, arg) - data = client.dnat_rules(**attrs) return ( @@ -246,4 +245,4 @@ def get_parser(self, prog_name): def take_action(self, parsed_args): client = self.app.client_manager.nat dnat_rule = client.get_dnat_rule(parsed_args.dnat_rule_id) - return client.delete_dnat_rule(dnat_rule.id) + client.delete_dnat_rule(dnat_rule.id) diff --git a/otcextensions/osclient/nat/v2/snat.py b/otcextensions/osclient/nat/v2/snat.py index 4391769d5..fb10cfb83 100644 --- a/otcextensions/osclient/nat/v2/snat.py +++ b/otcextensions/osclient/nat/v2/snat.py @@ -170,6 +170,7 @@ def get_parser(self, prog_name): parser.add_argument( '--net-id', metavar='', + dest='network_id', help=_('Specifies the network ID used by the SNAT rule. ' 'This parameter and cidr arealternative.')) parser.add_argument( @@ -224,4 +225,4 @@ def get_parser(self, prog_name): def take_action(self, parsed_args): client = self.app.client_manager.nat snat_rule = client.get_snat_rule(parsed_args.snat_rule_id) - return client.delete_snat_rule(snat_rule.id) + client.delete_snat_rule(snat_rule.id) diff --git a/otcextensions/sdk/nat/v2/dnat.py b/otcextensions/sdk/nat/v2/dnat.py index 5c71f7e2c..615f8f84c 100644 --- a/otcextensions/sdk/nat/v2/dnat.py +++ b/otcextensions/sdk/nat/v2/dnat.py @@ -1,69 +1,69 @@ -# 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. -from openstack import resource - - -class Dnat(resource.Resource): - resources_key = 'dnat_rules' - resource_key = 'dnat_rule' - base_path = '/dnat_rules' - - # capabilities - allow_create = True - allow_fetch = True - allow_delete = True - allow_list = True - - _query_mapping = resource.QueryParameters( - 'admin_state_up', 'cidr', 'created_at', 'external_service_port', - 'floating_ip_address', 'floating_ip_id', 'id', - 'internal_service_port', 'limit', 'nat_gateway_id', 'network_id', - 'port_id', 'private_id', 'protocol', 'source_type', 'status', - 'project_id' - ) - - # Properties - #: Specifies whether DNAT rule is enabled / disabled - #: *true:* DNAT rule is enabled - #: *false:* DNAT rule is disabled - admin_state_up = resource.Body('admin_state_up', type=bool) - #: Specifies when the rule is created. - #: The format is yyyy-mm-dd hh:mm:ss. - created_at = resource.Body('created_at') - #: Specifies the port for providing external services. - external_service_port = resource.Body('external_service_port', type=int) - #: Specifies the EIP - floating_ip_address = resource.Body('floating_ip_address') - #: Specifies the EIP ID - floating_ip_id = resource.Body('floating_ip_id') - #: Specifies the gateway ID. - gateway_id = resource.Body('gateway_id') - #: Specifies the ID of the DNAT rule. - id = resource.Body('id') - #: Specifies port used by ECS/BMS to provide services for external systems - internal_service_port = resource.Body('internal_service_port', type=int) - #: Specifies the ID of the NAT gateway. - nat_gateway_id = resource.Body('nat_gateway_id') - #: Specifies the port ID of an ECS or BMS - #: Parameter is used in the VPC scenario. - #: This parameter is an alternative to private_ip - port_id = resource.Body('port_id') - #: Specifies the IP address of a Direct Connect connection. - #: Parameter is used in the Direct Connect scenario. - #: This parameter is an alternative to port_id. - private_ip = resource.Body('private_ip') - #: Specifies the project ID. - project_id = resource.Body('tenant_id') - #: Specifies the protocol type. Currently TCP(6), UDP(17) and ANY(0) - protocol = resource.Body('protocol') - #: Specifies the status of the DNAT rule - status = resource.Body('status') +# 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. +from openstack import resource + + +class Dnat(resource.Resource): + resources_key = 'dnat_rules' + resource_key = 'dnat_rule' + base_path = '/dnat_rules' + + # capabilities + allow_create = True + allow_fetch = True + allow_delete = True + allow_list = True + + _query_mapping = resource.QueryParameters( + 'admin_state_up', 'cidr', 'created_at', 'external_service_port', + 'floating_ip_address', 'floating_ip_id', 'id', + 'internal_service_port', 'limit', 'nat_gateway_id', 'network_id', + 'port_id', 'private_ip', 'protocol', 'source_type', 'status', + 'tenant_id' + ) + + # Properties + #: Specifies whether DNAT rule is enabled / disabled + #: *true:* DNAT rule is enabled + #: *false:* DNAT rule is disabled + admin_state_up = resource.Body('admin_state_up', type=bool) + #: Specifies when the rule is created. + #: The format is yyyy-mm-dd hh:mm:ss. + created_at = resource.Body('created_at') + #: Specifies the port for providing external services. + external_service_port = resource.Body('external_service_port', type=int) + #: Specifies the EIP + floating_ip_address = resource.Body('floating_ip_address') + #: Specifies the EIP ID + floating_ip_id = resource.Body('floating_ip_id') + #: Specifies the gateway ID. + gateway_id = resource.Body('gateway_id') + #: Specifies the ID of the DNAT rule. + id = resource.Body('id') + #: Specifies port used by ECS/BMS to provide services for external systems + internal_service_port = resource.Body('internal_service_port', type=int) + #: Specifies the ID of the NAT gateway. + nat_gateway_id = resource.Body('nat_gateway_id') + #: Specifies the port ID of an ECS or BMS + #: Parameter is used in the VPC scenario. + #: This parameter is an alternative to private_ip + port_id = resource.Body('port_id') + #: Specifies the IP address of a Direct Connect connection. + #: Parameter is used in the Direct Connect scenario. + #: This parameter is an alternative to port_id. + private_ip = resource.Body('private_ip') + #: Specifies the project ID. + project_id = resource.Body('tenant_id') + #: Specifies the protocol type. Currently TCP(6), UDP(17) and ANY(0) + protocol = resource.Body('protocol') + #: Specifies the status of the DNAT rule + status = resource.Body('status') diff --git a/otcextensions/tests/functional/osclient/nat/v2/test_dnat_rule.py b/otcextensions/tests/functional/osclient/nat/v2/test_dnat_rule.py new file mode 100644 index 000000000..8dc97bc3f --- /dev/null +++ b/otcextensions/tests/functional/osclient/nat/v2/test_dnat_rule.py @@ -0,0 +1,181 @@ +# 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 json +import uuid + +from openstackclient.tests.functional import base + + +class TestDnatRule(base.TestCase): + """Functional Tests for NAT Gateway""" + + UUID = uuid.uuid4().hex[:8] + ROUTER_NAME = 'sdk-test-router-' + UUID + NET_NAME = 'sdk-test-net-' + UUID + SUBNET_NAME = 'sdk-test-subnet-' + UUID + PORT_NAME = 'sdk-test-port-' + UUID + ROUTER_ID = None + NET_ID = None + FLOATING_IP_ID = None + PORT_ID = None + + NAT_NAME = 'os-cli-test-' + UUID + NAT_ID = None + DNAT_RULE_ID = None + + def test_01_nat_dnat_rule_list(self): + self.openstack( + 'nat dnat rule list -f json ' + ) + + def test_02_nat_dnat_rule_list_filters(self): + self.openstack( + 'nat dnat rule list ' + '--limit 1 --id 2 ' + '--project-id 3 ' + '--port-id 4 ' + '--private-ip 5 ' + '--internal-service-port 6 ' + '--floating-ip-id 7 ' + '--floating-ip-address 8 ' + '--external-service-port 9 ' + '--status 10 ' + '--protocol tcp ' + '--admin-state-up true ' + ) + + def test_03_nat_dnat_rule_create(self): + self._create_nat_gateway() + self.assertIsNotNone(self.PORT_ID) + self.assertIsNotNone(self.FLOATING_IP_ID) + json_output = json.loads(self.openstack( + 'nat dnat rule create ' + '{nat_id} {floating_ip_id} ' + '--protocol TCP ' + '--internal-service-port 80 ' + '--external-service-port 80 ' + '--private-ip {private_ip} ' + '-f json'.format( + nat_id=self.NAT_ID, + private_ip='192.168.0.3', + floating_ip_id=self.FLOATING_IP_ID) + )) + TestDnatRule.DNAT_RULE_ID = json_output['id'] + + def test_04_nat_dnat_rule_list_by_id(self): + self.assertIsNotNone(self.DNAT_RULE_ID) + json_output = json.loads(self.openstack( + 'nat dnat rule list -f json ' + '--id ' + self.DNAT_RULE_ID + )) + self.assertIsNotNone(json_output) + + def test_05_nat_dnat_rule_show(self): + self.assertIsNotNone(self.DNAT_RULE_ID) + json_output = json.loads(self.openstack( + 'nat dnat rule show ' + ' -f json ' + self.DNAT_RULE_ID + )) + self.assertIsNotNone(json_output) + + def test_11_nat_dnat_rule_delete(self): + self.addCleanup(self._delete_nat_gateway) + self.assertIsNotNone(self.NAT_ID) + self.assertIsNotNone(self.DNAT_RULE_ID) + self.openstack( + 'nat dnat rule delete ' + self.DNAT_RULE_ID) + + def _create_nat_gateway(self): + self._initialize_network() + json_output = json.loads(self.openstack( + 'nat gateway create {name}' + ' --router-id {router_id}' + ' --internal-network-id {net_id}' + ' --spec {spec} -f json'.format( + name=self.NAT_NAME, + router_id=self.ROUTER_ID, + net_id=self.NET_ID, + description='OTCE Lib Test', + spec=1) + )) + TestDnatRule.NAT_ID = json_output['id'] + + def _delete_nat_gateway(self): + self.addCleanup(self._denitialize_network) + self.openstack('nat gateway delete ' + self.NAT_ID) + + def _initialize_network(self): + router = json.loads(self.openstack( + 'router create -f json ' + self.ROUTER_NAME + )) + net = json.loads(self.openstack( + 'network create -f json ' + self.NET_NAME + )) + self.openstack( + 'subnet create {subnet} -f json ' + '--network {net} ' + '--subnet-range 192.168.0.0/24 '.format( + subnet=self.SUBNET_NAME, + net=self.NET_NAME + )) + + self.openstack( + 'router add subnet {router} ' + '{subnet} '.format( + router=self.ROUTER_NAME, + subnet=self.SUBNET_NAME + ) + ) + + floating_ip = json.loads(self.openstack( + 'floating ip create -f json ' + '{network}'.format( + network='admin_external_net') + )) + + TestDnatRule.ROUTER_ID = router['id'] + TestDnatRule.NET_ID = net['id'] + TestDnatRule.FLOATING_IP_ID = floating_ip['id'] + + port = json.loads(self.openstack( + 'port create {name} ' + '--network {net_id} ' + '-f json'.format( + name=self.PORT_NAME, + net_id=self.NET_ID) + )) + TestDnatRule.PORT_ID = port['id'] + + def _denitialize_network(self): + self.openstack( + 'port delete ' + self.PORT_NAME + ) + self.openstack( + 'router remove subnet {router} ' + '{subnet} '.format( + router=self.ROUTER_NAME, + subnet=self.SUBNET_NAME + ) + ) + self.openstack( + 'subnet delete ' + self.SUBNET_NAME + ) + self.openstack( + 'network delete ' + self.NET_NAME + ) + self.openstack( + 'router delete ' + self.ROUTER_NAME + ) + self.openstack( + 'floating ip delete ' + self.FLOATING_IP_ID + ) diff --git a/otcextensions/tests/functional/osclient/nat/v2/test_snat_rule.py b/otcextensions/tests/functional/osclient/nat/v2/test_snat_rule.py new file mode 100644 index 000000000..2db3379ec --- /dev/null +++ b/otcextensions/tests/functional/osclient/nat/v2/test_snat_rule.py @@ -0,0 +1,181 @@ +# 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 json +import uuid + +from openstackclient.tests.functional import base +from tempest.lib.exceptions import CommandFailed + + +class TestSnatRule(base.TestCase): + """Functional Tests for NAT Gateway""" + + UUID = uuid.uuid4().hex[:8] + ROUTER_NAME = 'sdk-test-router-' + UUID + NET_NAME = 'sdk-test-net-' + UUID + SUBNET_NAME = 'sdk-test-subnet-' + UUID + ROUTER_ID = None + NET_ID = None + FLOATING_IP_ID = None + + NAT_NAME = 'os-cli-test-' + UUID + NAT_ID = None + SNAT_RULE_ID = None + + def test_01_snat_rule_list(self): + self.openstack( + 'nat snat rule list -f json ' + ) + + def test_02_snat_rule_list_filters(self): + self.openstack( + 'nat snat rule list ' + '--limit 1 --id 2 ' + '--project-id 3 ' + '--nat-gateway-id 4 ' + '--network-id 5 ' + '--cidr 6 ' + '--source-type 7 ' + '--floating-ip-id 8 ' + '--floating-ip-address 9 ' + '--status 10 ' + '--admin-state-up true ' + ) + + def test_03_nat_snat_rule_create(self): + self._create_nat_gateway() + self.assertIsNotNone(self.NAT_ID) + self.assertIsNotNone(self.FLOATING_IP_ID) + json_output = json.loads(self.openstack( + 'nat snat rule create ' + '{nat_id} {floating_ip_id} ' + '--net-id {net_id} -f json'.format( + nat_id=self.NAT_ID, + floating_ip_id=self.FLOATING_IP_ID, + net_id=self.NET_ID) + )) + TestSnatRule.SNAT_RULE_ID = json_output['id'] + + def test_04_nat_snat_rule_list_by_id(self): + self.assertIsNotNone(self.SNAT_RULE_ID) + json_output = json.loads(self.openstack( + 'nat snat rule list -f json ' + '--id ' + self.SNAT_RULE_ID + )) + self.assertIsNotNone(json_output) + + def test_05_nat_snat_rule_show(self): + self.assertIsNotNone(self.SNAT_RULE_ID) + json_output = json.loads(self.openstack( + 'nat snat rule show ' + ' -f json ' + self.SNAT_RULE_ID + )) + self.assertIsNotNone(json_output) + + def test_06_nat_snat_rule_create_for_existing_network(self): + self.assertIsNotNone(self.NAT_ID) + self.assertIsNotNone(self.FLOATING_IP_ID) + self.assertRaises( + CommandFailed, + self.openstack, + 'nat snat rule create ' + '{nat_id} {floating_ip_id} ' + '--net-id {net_id} -f json'.format( + nat_id=self.NAT_ID, + floating_ip_id=self.FLOATING_IP_ID, + net_id=self.NET_ID) + ) + + def test_07_nat_snat_rule_create_cidr_source_type(self): + self.assertIsNotNone(self.NAT_ID) + self.assertIsNotNone(self.FLOATING_IP_ID) + + def test_11_nat_snat_rule_delete(self): + self.addCleanup(self._delete_nat_gateway) + self.assertIsNotNone(self.NAT_ID) + self.assertIsNotNone(self.SNAT_RULE_ID) + self.openstack( + 'nat snat rule delete ' + self.SNAT_RULE_ID) + + def _create_nat_gateway(self): + self._initialize_network() + json_output = json.loads(self.openstack( + 'nat gateway create {name}' + ' --router-id {router_id}' + ' --internal-network-id {net_id}' + ' --spec {spec} -f json'.format( + name=self.NAT_NAME, + router_id=self.ROUTER_ID, + net_id=self.NET_ID, + description='OTCE Lib Test', + spec=1) + )) + TestSnatRule.NAT_ID = json_output['id'] + + def _delete_nat_gateway(self): + self.addCleanup(self._denitialize_network) + self.openstack('nat gateway delete ' + self.NAT_ID) + + def _initialize_network(self): + router = json.loads(self.openstack( + 'router create -f json ' + self.ROUTER_NAME + )) + net = json.loads(self.openstack( + 'network create -f json ' + self.NET_NAME + )) + self.openstack( + 'subnet create {subnet} -f json ' + '--network {net} ' + '--subnet-range 192.168.0.0/24 '.format( + subnet=self.SUBNET_NAME, + net=self.NET_NAME + )) + + self.openstack( + 'router add subnet {router} ' + '{subnet} '.format( + router=self.ROUTER_NAME, + subnet=self.SUBNET_NAME + ) + ) + + floating_ip = json.loads(self.openstack( + 'floating ip create -f json ' + '{network}'.format( + network='admin_external_net') + )) + + TestSnatRule.ROUTER_ID = router['id'] + TestSnatRule.NET_ID = net['id'] + TestSnatRule.FLOATING_IP_ID = floating_ip['id'] + + def _denitialize_network(self): + self.openstack( + 'router remove subnet {router} ' + '{subnet} '.format( + router=self.ROUTER_NAME, + subnet=self.SUBNET_NAME + ) + ) + self.openstack( + 'subnet delete ' + self.SUBNET_NAME + ) + self.openstack( + 'network delete ' + self.NET_NAME + ) + self.openstack( + 'router delete ' + self.ROUTER_NAME + ) + self.openstack( + 'floating ip delete ' + self.FLOATING_IP_ID + ) From f66fdb7e1beefe387ae8853982b0651eda29ffc2 Mon Sep 17 00:00:00 2001 From: Vineet Pruthi Date: Wed, 11 Mar 2020 08:30:36 +0000 Subject: [PATCH 22/73] Updated documentation for NAT --- doc/source/cli/index.rst | 52 +++++++------------- doc/source/cli/nat.rst | 36 ++++++++++++++ doc/source/enforcer.py | 1 + doc/source/user/guides/nat.rst | 4 ++ doc/source/user/proxies/nat_v2.rst | 48 ++++++++++++++++++ doc/source/user/resources/nat/index.rst | 9 ++++ doc/source/user/resources/nat/v2/dnat.rst | 13 +++++ doc/source/user/resources/nat/v2/gateway.rst | 13 +++++ doc/source/user/resources/nat/v2/snat.rst | 13 +++++ 9 files changed, 154 insertions(+), 35 deletions(-) create mode 100644 doc/source/cli/nat.rst create mode 100644 doc/source/user/guides/nat.rst create mode 100644 doc/source/user/proxies/nat_v2.rst create mode 100644 doc/source/user/resources/nat/index.rst create mode 100644 doc/source/user/resources/nat/v2/dnat.rst create mode 100644 doc/source/user/resources/nat/v2/gateway.rst create mode 100644 doc/source/user/resources/nat/v2/snat.rst diff --git a/doc/source/cli/index.rst b/doc/source/cli/index.rst index c4d31c1f4..02343465b 100644 --- a/doc/source/cli/index.rst +++ b/doc/source/cli/index.rst @@ -1,38 +1,20 @@ -OpenStack Client (CLI) -====================== - -The OpenStack Client is a self-contained OpenStack project providing a -command line interface to the most important cloud functions. For most -of the API calls an equivalent CLI command is available under a shared -command invoked as ``openstack``. An example is ``openstack server -list``. For reference see the documentation of the OpenStack Client -(OSC). - -The OTC Extensions don't re-implement the CLI tool, but augment it -automatically. If you have installed OTC Extensions and OpenStack -Client, the latter understands many extra commands: - -.. code-block:: bash - - openstack --help | grep -c otcextensions - 164 - -For details of the available commands, check the detailed CLI -documentation of these services: +OpenStackClient CLI Usage +========================= .. toctree:: - :maxdepth: 1 + :maxdepth: 2 - anti_ddos - auto_scaling - cce_v2 - cts - dcs - deh - dms - dns - kms - load_balancer - obs - rds - volume_backup + anti_ddos.rst + auto_scaling.rst + cce_v2.rst + cts.rst + dcs.rst + deh.rst + dms.rst + dns.rst + rds.rst + kms.rst + nat.rst + load_balancer.rst + obs.rst + volume_backup.rst diff --git a/doc/source/cli/nat.rst b/doc/source/cli/nat.rst new file mode 100644 index 000000000..f13c377df --- /dev/null +++ b/doc/source/cli/nat.rst @@ -0,0 +1,36 @@ +========================================== +Database service (rds) command-line client +========================================== + +The RDS client is the command-line interface (CLI) for +the Database service (RDS) API and its extensions. + +For help on a specific `nat` command, enter: + +.. code-block:: console + + $ openstack nat help SUBCOMMAND + +.. _gateway: + +NAT Gateway operations +-------------------- + +.. autoprogram-cliff:: openstack.nat.v2 + :command: nat gateway * + +.. _snat: + +SNAT Rule operations +----------------- + +.. autoprogram-cliff:: openstack.nat.v2 + :command: nat snat * + +.. _dnat: + +DNAT Rule operations +------------------- + +.. autoprogram-cliff:: openstack.nat.v2 + :command: nat dnat * diff --git a/doc/source/enforcer.py b/doc/source/enforcer.py index 7c6d46953..87f472bce 100644 --- a/doc/source/enforcer.py +++ b/doc/source/enforcer.py @@ -50,6 +50,7 @@ def get_proxy_methods(): "otcextensions.sdk.obs.v1._proxy", "otcextensions.sdk.rds.v1._proxy", "otcextensions.sdk.rds.v3._proxy", + "otcextensions.sdk.nat.v2._proxy", "otcextensions.sdk.volume_backup.v2._proxy" ] diff --git a/doc/source/user/guides/nat.rst b/doc/source/user/guides/nat.rst new file mode 100644 index 000000000..8553150ba --- /dev/null +++ b/doc/source/user/guides/nat.rst @@ -0,0 +1,4 @@ +Using OTC NAT +============= + +.. TODO(agoncharov): Implement this guide diff --git a/doc/source/user/proxies/nat_v2.rst b/doc/source/user/proxies/nat_v2.rst new file mode 100644 index 000000000..7ec2c4df3 --- /dev/null +++ b/doc/source/user/proxies/nat_v2.rst @@ -0,0 +1,48 @@ +Database NAT API +================ + +For details on how to use database, see :doc:`/user/guides/rds` + +.. automodule:: otcextensions.sdk.nat.v2._proxy + +The NAT Class +-------------- + +The NAT high-level interface is available through the ``nat`` member of a +:class:`~openstack.connection.Connection` object. The ``nat`` member will only +be added if the ``otcextensions.sdk.register_otc_extensions(conn)`` method is +called. + +NAT Gateway Operations +^^^^^^^^^^^^^^^^^^^^^^ + +.. autoclass:: otcextensions.sdk.nat.v2._proxy.Proxy + + .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.create_gateway + .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.update_gateway + .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.delete_gateway + .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.get_gateway + .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.find_gateway + .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.gateways + + +NAT Snat Rule Operations +^^^^^^^^^^^^^^^^^^^^^^^^ + +.. autoclass:: otcextensions.sdk.nat.v2._proxy.Proxy + + .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.create_snat_rule + .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.delete_snat_rule + .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.get_snat_rule + .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.delete_snat_rule + + +NAT Dnat Rule Operations +^^^^^^^^^^^^^^^^^^^^^^^^ + +.. autoclass:: otcextensions.sdk.nat.v2._proxy.Proxy + + .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.create_dnat_rule + .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.delete_dnat_rule + .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.get_dnat_rule + .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.delete_dnat_rule diff --git a/doc/source/user/resources/nat/index.rst b/doc/source/user/resources/nat/index.rst new file mode 100644 index 000000000..712e949da --- /dev/null +++ b/doc/source/user/resources/nat/index.rst @@ -0,0 +1,9 @@ +NAT Resources +============= + +.. toctree:: + :maxdepth: 1 + + v2/gateway + v2/snat + v2/dnat diff --git a/doc/source/user/resources/nat/v2/dnat.rst b/doc/source/user/resources/nat/v2/dnat.rst new file mode 100644 index 000000000..6b26243ee --- /dev/null +++ b/doc/source/user/resources/nat/v2/dnat.rst @@ -0,0 +1,13 @@ +otcextensions.sdk.nat.v2.dnat +============================= + +.. automodule:: otcextensions.sdk.nat.v2.dnat + +The Dnat Class +-------------- + +The ``Dnat`` class inherits from +:class:`~otcextensions.sdk.sdk_resource.Resource`. + +.. autoclass:: otcextensions.sdk.nat.v2.dnat.Dnat + :members: diff --git a/doc/source/user/resources/nat/v2/gateway.rst b/doc/source/user/resources/nat/v2/gateway.rst new file mode 100644 index 000000000..8d30e9838 --- /dev/null +++ b/doc/source/user/resources/nat/v2/gateway.rst @@ -0,0 +1,13 @@ +otcextensions.sdk.nat.v2.gateway +================================ + +.. automodule:: otcextensions.sdk.nat.v2.gateway + +The Instance Class +------------------ + +The ``Gateway`` class inherits from +:class:`~otcextensions.sdk.sdk_resource.Resource`. + +.. autoclass:: otcextensions.sdk.nat.v2.gateway.Gateway + :members: diff --git a/doc/source/user/resources/nat/v2/snat.rst b/doc/source/user/resources/nat/v2/snat.rst new file mode 100644 index 000000000..ea55439ee --- /dev/null +++ b/doc/source/user/resources/nat/v2/snat.rst @@ -0,0 +1,13 @@ +otcextensions.sdk.nat.v2.snat +============================= + +.. automodule:: otcextensions.sdk.nat.v2.snat + +The Instance Class +------------------ + +The ``Dnat`` class inherits from +:class:`~otcextensions.sdk.sdk_resource.Resource`. + +.. autoclass:: otcextensions.sdk.nat.v2.snat.Snat + :members: From a605a30541fe1e7984041860b506d466ab7763dd Mon Sep 17 00:00:00 2001 From: Vineet Pruthi Date: Wed, 11 Mar 2020 09:13:31 +0000 Subject: [PATCH 23/73] Fixed nat.rst erros --- doc/source/cli/nat.rst | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/doc/source/cli/nat.rst b/doc/source/cli/nat.rst index f13c377df..96b1fe5ae 100644 --- a/doc/source/cli/nat.rst +++ b/doc/source/cli/nat.rst @@ -1,9 +1,9 @@ -========================================== -Database service (rds) command-line client -========================================== +===================================================== +Network Address Translation (nat) command-line client +===================================================== -The RDS client is the command-line interface (CLI) for -the Database service (RDS) API and its extensions. +The NAT client is the command-line interface (CLI) for +the Database service (NAT) API and its extensions. For help on a specific `nat` command, enter: @@ -14,7 +14,7 @@ For help on a specific `nat` command, enter: .. _gateway: NAT Gateway operations --------------------- +---------------------- .. autoprogram-cliff:: openstack.nat.v2 :command: nat gateway * @@ -22,7 +22,7 @@ NAT Gateway operations .. _snat: SNAT Rule operations ------------------ +-------------------- .. autoprogram-cliff:: openstack.nat.v2 :command: nat snat * @@ -30,7 +30,7 @@ SNAT Rule operations .. _dnat: DNAT Rule operations -------------------- +-------------------- .. autoprogram-cliff:: openstack.nat.v2 :command: nat dnat * From 97da2955d17f731eb4f7eebd4f620ae1d6b0f72e Mon Sep 17 00:00:00 2001 From: Vineet Pruthi Date: Thu, 12 Mar 2020 10:21:45 +0000 Subject: [PATCH 24/73] Updated Functional Tests --- .../osclient/nat/v2/test_dnat_rule.py | 20 +++++++++-- .../osclient/nat/v2/test_snat_rule.py | 36 ++++++++++++++++--- 2 files changed, 50 insertions(+), 6 deletions(-) diff --git a/otcextensions/tests/functional/osclient/nat/v2/test_dnat_rule.py b/otcextensions/tests/functional/osclient/nat/v2/test_dnat_rule.py index 8dc97bc3f..837f2f319 100644 --- a/otcextensions/tests/functional/osclient/nat/v2/test_dnat_rule.py +++ b/otcextensions/tests/functional/osclient/nat/v2/test_dnat_rule.py @@ -50,6 +50,7 @@ def test_02_nat_dnat_rule_list_filters(self): '--floating-ip-address 8 ' '--external-service-port 9 ' '--status 10 ' + '--nat-gateway-id 11 ' '--protocol tcp ' '--admin-state-up true ' ) @@ -70,6 +71,7 @@ def test_03_nat_dnat_rule_create(self): private_ip='192.168.0.3', floating_ip_id=self.FLOATING_IP_ID) )) + self.assertIsNotNone(json_output) TestDnatRule.DNAT_RULE_ID = json_output['id'] def test_04_nat_dnat_rule_list_by_id(self): @@ -79,16 +81,30 @@ def test_04_nat_dnat_rule_list_by_id(self): '--id ' + self.DNAT_RULE_ID )) self.assertIsNotNone(json_output) + self.assertEqual(next(iter(json_output))['Id'], self.DNAT_RULE_ID) + self.assertEqual( + next(iter(json_output))['Nat Gateway Id'], self.NAT_ID) + + def test_05_nat_dnat_rule_list_by_nat_id(self): + self.assertIsNotNone(self.DNAT_RULE_ID) + json_output = json.loads(self.openstack( + 'nat dnat rule list -f json ' + '--nat-gateway-id ' + self.NAT_ID + )) + self.assertIsNotNone(json_output) + self.assertEqual( + next(iter(json_output))['Nat Gateway Id'], self.NAT_ID) - def test_05_nat_dnat_rule_show(self): + def test_06_nat_dnat_rule_show(self): self.assertIsNotNone(self.DNAT_RULE_ID) json_output = json.loads(self.openstack( 'nat dnat rule show ' ' -f json ' + self.DNAT_RULE_ID )) self.assertIsNotNone(json_output) + self.assertEqual(json_output['id'], self.DNAT_RULE_ID) - def test_11_nat_dnat_rule_delete(self): + def test_07_nat_dnat_rule_delete(self): self.addCleanup(self._delete_nat_gateway) self.assertIsNotNone(self.NAT_ID) self.assertIsNotNone(self.DNAT_RULE_ID) diff --git a/otcextensions/tests/functional/osclient/nat/v2/test_snat_rule.py b/otcextensions/tests/functional/osclient/nat/v2/test_snat_rule.py index 2db3379ec..4460f6235 100644 --- a/otcextensions/tests/functional/osclient/nat/v2/test_snat_rule.py +++ b/otcextensions/tests/functional/osclient/nat/v2/test_snat_rule.py @@ -64,6 +64,7 @@ def test_03_nat_snat_rule_create(self): floating_ip_id=self.FLOATING_IP_ID, net_id=self.NET_ID) )) + self.assertIsNotNone(json_output) TestSnatRule.SNAT_RULE_ID = json_output['id'] def test_04_nat_snat_rule_list_by_id(self): @@ -73,16 +74,30 @@ def test_04_nat_snat_rule_list_by_id(self): '--id ' + self.SNAT_RULE_ID )) self.assertIsNotNone(json_output) + self.assertEqual(next(iter(json_output))['Id'], self.SNAT_RULE_ID) + self.assertEqual( + next(iter(json_output))['Nat Gateway Id'], self.NAT_ID) + + def test_05_nat_snat_rule_list_by_nat_id(self): + self.assertIsNotNone(self.SNAT_RULE_ID) + json_output = json.loads(self.openstack( + 'nat snat rule list -f json ' + '--nat-gateway-id ' + self.NAT_ID + )) + self.assertIsNotNone(json_output) + self.assertEqual( + next(iter(json_output))['Nat Gateway Id'], self.NAT_ID) - def test_05_nat_snat_rule_show(self): + def test_06_nat_snat_rule_show(self): self.assertIsNotNone(self.SNAT_RULE_ID) json_output = json.loads(self.openstack( 'nat snat rule show ' ' -f json ' + self.SNAT_RULE_ID )) self.assertIsNotNone(json_output) + self.assertEqual(json_output['id'], self.SNAT_RULE_ID) - def test_06_nat_snat_rule_create_for_existing_network(self): + def test_07_nat_snat_rule_create_for_existing_network(self): self.assertIsNotNone(self.NAT_ID) self.assertIsNotNone(self.FLOATING_IP_ID) self.assertRaises( @@ -96,11 +111,24 @@ def test_06_nat_snat_rule_create_for_existing_network(self): net_id=self.NET_ID) ) - def test_07_nat_snat_rule_create_cidr_source_type(self): + def test_08_nat_snat_rule_create_cidr_source_type(self): self.assertIsNotNone(self.NAT_ID) self.assertIsNotNone(self.FLOATING_IP_ID) + json_output = json.loads(self.openstack( + 'nat snat rule create ' + '{nat_id} {floating_ip_id} ' + '--source-type {source_type} ' + '--cidr {cidr} -f json'.format( + nat_id=self.NAT_ID, + floating_ip_id=self.FLOATING_IP_ID, + source_type=1, + cidr='192.168.5.0/24') + )) + self.assertEqual(json_output['source_type'], 1) + self.openstack( + 'nat snat rule delete ' + json_output['id']) - def test_11_nat_snat_rule_delete(self): + def test_09_nat_snat_rule_delete(self): self.addCleanup(self._delete_nat_gateway) self.assertIsNotNone(self.NAT_ID) self.assertIsNotNone(self.SNAT_RULE_ID) From 4abec7ad535322e399a736bb57bc4babef1af038 Mon Sep 17 00:00:00 2001 From: Vineet Pruthi Date: Mon, 16 Mar 2020 07:21:32 +0000 Subject: [PATCH 25/73] Usage of project_id in list nat functions query params --- otcextensions/osclient/nat/v2/dnat.py | 11 +- otcextensions/osclient/nat/v2/gateway.py | 16 ++- otcextensions/osclient/nat/v2/snat.py | 15 ++- otcextensions/sdk/nat/v2/dnat.py | 8 +- otcextensions/sdk/nat/v2/gateway.py | 2 +- otcextensions/sdk/nat/v2/snat.py | 124 +++++++++--------- .../osclient/nat/v2/test_dnat_rule.py | 9 +- .../osclient/nat/v2/test_nat_gateway.py | 9 +- .../osclient/nat/v2/test_snat_rule.py | 12 +- .../tests/unit/osclient/nat/v2/test_dnat.py | 4 +- .../unit/osclient/nat/v2/test_gateway.py | 4 +- .../tests/unit/osclient/nat/v2/test_snat.py | 4 +- 12 files changed, 118 insertions(+), 100 deletions(-) diff --git a/otcextensions/osclient/nat/v2/dnat.py b/otcextensions/osclient/nat/v2/dnat.py index 983b07aa6..2254e4b8a 100644 --- a/otcextensions/osclient/nat/v2/dnat.py +++ b/otcextensions/osclient/nat/v2/dnat.py @@ -55,8 +55,7 @@ def get_parser(self, prog_name): help=_('Limit to fetch number of records.')) parser.add_argument( '--project-id', - metavar='', - dest='tenant_id', + metavar='', help=_('Specifies the project ID.')) parser.add_argument( '--nat-gateway-id', @@ -114,7 +113,7 @@ def take_action(self, parsed_args): args_list = [ 'id', 'limit', - 'tenant_id', + 'project_id', 'nat_gateway_id', 'port_id', 'private_ip', @@ -185,20 +184,24 @@ def get_parser(self, prog_name): parser.add_argument( '--internal-service-port', metavar='', + required=True, help=_('Specifies port used by ECSs or BMSs toprovide ' 'services for external systems.')) parser.add_argument( - 'floating_ip_id', + '--floating-ip-id', metavar="", + required=True, help=_('Specifies the EIP ID. Multiple EIPs are ' 'separated using commas')) parser.add_argument( '--external-service-port', metavar='', + required=True, help=_('Specifies the port for providing external services.')) parser.add_argument( '--protocol', metavar='', + required=True, help=_('Specifies the protocol type.')) return parser diff --git a/otcextensions/osclient/nat/v2/gateway.py b/otcextensions/osclient/nat/v2/gateway.py index 7db142c63..a12c033ab 100644 --- a/otcextensions/osclient/nat/v2/gateway.py +++ b/otcextensions/osclient/nat/v2/gateway.py @@ -47,8 +47,7 @@ def get_parser(self, prog_name): help=_('Limit to fetch number of records.')) parser.add_argument( '--project-id', - metavar='', - dest='tenant_id', + metavar='', help=_('Specifies the project ID.')) parser.add_argument( '--name', @@ -89,7 +88,7 @@ def take_action(self, parsed_args): args_list = [ 'id', 'limit', - 'tenant_id', + 'project_id', 'name', 'spec', 'router_id', @@ -146,14 +145,23 @@ def get_parser(self, prog_name): parser.add_argument( '--spec', metavar="", - help=_("Specifies the type of the NAT gateway.")) + required=True, + help=_( + "Specifies the type of the NAT gateway." + "\n1: small type, which supports up to 10,000 " + "SNAT connections.\n2: medium type, which supports " + "up to 50,000 SNAT connections.\n3: large type, which " + "supports up to 200,000 SNAT connections.\n4: extra-large " + "type, which supports up to 1,000,000 SNAT connections.")) parser.add_argument( '--router-id', metavar="", + required=True, help=_("Specifies the VPC ID")) parser.add_argument( '--internal-network-id', metavar="", + required=True, help=_("Specifies the network ID of thedownstream interface " "(the next hop ofthe DVR) of the NAT gateway.")) diff --git a/otcextensions/osclient/nat/v2/snat.py b/otcextensions/osclient/nat/v2/snat.py index fb10cfb83..76f52ac06 100644 --- a/otcextensions/osclient/nat/v2/snat.py +++ b/otcextensions/osclient/nat/v2/snat.py @@ -54,8 +54,7 @@ def get_parser(self, prog_name): help=_('Limit to fetch number of records.')) parser.add_argument( '--project-id', - metavar='', - dest='tenant_id', + metavar='', help=_('Specifies the project ID.')) parser.add_argument( '--nat-gateway-id', @@ -105,7 +104,7 @@ def take_action(self, parsed_args): 'id', 'limit', 'network_id', - 'tenant_id', + 'project_id', 'nat_gateway_id', 'network_id', 'cidr', @@ -163,8 +162,9 @@ def get_parser(self, prog_name): metavar='', help=_('Specifies the ID of the NAT gateway')) parser.add_argument( - 'floating_ip_id', + '--floating-ip-id', metavar='', + required=True, help=_('Specifies the EIP ID. Multiple EIPs ' 'are separated using commas')) parser.add_argument( @@ -181,7 +181,12 @@ def get_parser(self, prog_name): parser.add_argument( '--source-type', metavar='', - help=_('Specifies the source type.')) + help=_( + 'Specifies the source type.\n0: Either network_id ' + 'or cidr can be specified in a VPC.\n1: Only cidr ' + 'can be specified over a Direct Connect connection.' + '\nIf no value is entered, the default value 0 (VPC) ' + 'is used.')) return parser diff --git a/otcextensions/sdk/nat/v2/dnat.py b/otcextensions/sdk/nat/v2/dnat.py index 615f8f84c..f03efea6a 100644 --- a/otcextensions/sdk/nat/v2/dnat.py +++ b/otcextensions/sdk/nat/v2/dnat.py @@ -25,10 +25,10 @@ class Dnat(resource.Resource): _query_mapping = resource.QueryParameters( 'admin_state_up', 'cidr', 'created_at', 'external_service_port', - 'floating_ip_address', 'floating_ip_id', 'id', - 'internal_service_port', 'limit', 'nat_gateway_id', 'network_id', - 'port_id', 'private_ip', 'protocol', 'source_type', 'status', - 'tenant_id' + 'floating_ip_address', 'floating_ip_id', 'id', 'internal_service_port', + 'limit', 'nat_gateway_id', 'network_id', 'port_id', 'private_ip', + 'protocol', 'source_type', 'status', 'project_id', + project_id='tenant_id' ) # Properties diff --git a/otcextensions/sdk/nat/v2/gateway.py b/otcextensions/sdk/nat/v2/gateway.py index bcacd7f32..b93901ebb 100644 --- a/otcextensions/sdk/nat/v2/gateway.py +++ b/otcextensions/sdk/nat/v2/gateway.py @@ -27,7 +27,7 @@ class Gateway(resource.Resource): _query_mapping = resource.QueryParameters( 'admin_state_up', 'created_at', 'description', 'id', 'internal_network_id', 'limit', 'name', 'router_id', - 'spec', 'status', 'project_id' + 'spec', 'status', 'project_id', project_id='tenant_id' ) # Properties diff --git a/otcextensions/sdk/nat/v2/snat.py b/otcextensions/sdk/nat/v2/snat.py index c4fdf5fb5..ad5dc0cb1 100644 --- a/otcextensions/sdk/nat/v2/snat.py +++ b/otcextensions/sdk/nat/v2/snat.py @@ -1,62 +1,62 @@ -# 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. -from openstack import resource - - -class Snat(resource.Resource): - resources_key = 'snat_rules' - resource_key = 'snat_rule' - base_path = '/snat_rules' - - # capabilities - allow_create = True - allow_fetch = True - allow_delete = True - allow_list = True - - _query_mapping = resource.QueryParameters( - 'admin_state_up', 'cidr', 'created_at', 'floating_ip_address', - 'floating_ip_id', 'id', 'limit', 'nat_gateway_id', 'network_id', - 'source_type', 'status', 'tenant_id' - ) - - # Properties - #: Specifies the status of the SNAT rule - admin_state_up = resource.Body('admin_state_up', type=bool) - #: Specifies a subset of the VPC subnet CIDR block or a - #: CIDR block of Direct Connect connection. - cidr = resource.Body('cidr') - #: Specifies when the rule is created. - #: The format is yyyy-mm-dd hh:mm:ss. - created_at = resource.Body('created_at') - #: Specifies the EIP - #: Multiple EIPs are separated using commas - floating_ip_address = resource.Body('floating_ip_address') - #: Specifies the EIP ID - #: Multiple EIPs are separated using commas - floating_ip_id = resource.Body('floating_ip_id') - #: Specifies the ID of the SNAT rule. - id = resource.Body('id') - #: Specifies the gateway ID. - nat_gateway_id = resource.Body('nat_gateway_id') - #: Specifies the network ID - network_id = resource.Body('network_id') - #: Specifies the project ID. - project_id = resource.Body('tenant_id') - #: *0:* Either network_id or cidr can be specified in VPC - #: *1:* only cidr can be specified over a Direct Connect connection - #: Default: 0 - source_type = resource.Body('source_type', type=int) - #: Specifies whether SNAT rule is enabled / disabled - #: *true:* SNAT rule is enabled - #: *false:* SNAT rule is disabled - status = resource.Body('status') +# 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. +from openstack import resource + + +class Snat(resource.Resource): + resources_key = 'snat_rules' + resource_key = 'snat_rule' + base_path = '/snat_rules' + + # capabilities + allow_create = True + allow_fetch = True + allow_delete = True + allow_list = True + + _query_mapping = resource.QueryParameters( + 'admin_state_up', 'cidr', 'created_at', 'floating_ip_address', + 'floating_ip_id', 'id', 'limit', 'nat_gateway_id', 'network_id', + 'source_type', 'status', 'project_id', project_id='tenant_id' + ) + + # Properties + #: Specifies the status of the SNAT rule + admin_state_up = resource.Body('admin_state_up', type=bool) + #: Specifies a subset of the VPC subnet CIDR block or a + #: CIDR block of Direct Connect connection. + cidr = resource.Body('cidr') + #: Specifies when the rule is created. + #: The format is yyyy-mm-dd hh:mm:ss. + created_at = resource.Body('created_at') + #: Specifies the EIP + #: Multiple EIPs are separated using commas + floating_ip_address = resource.Body('floating_ip_address') + #: Specifies the EIP ID + #: Multiple EIPs are separated using commas + floating_ip_id = resource.Body('floating_ip_id') + #: Specifies the ID of the SNAT rule. + id = resource.Body('id') + #: Specifies the gateway ID. + nat_gateway_id = resource.Body('nat_gateway_id') + #: Specifies the network ID + network_id = resource.Body('network_id') + #: Specifies the project ID. + project_id = resource.Body('tenant_id') + #: *0:* Either network_id or cidr can be specified in VPC + #: *1:* only cidr can be specified over a Direct Connect connection + #: Default: 0 + source_type = resource.Body('source_type', type=int) + #: Specifies whether SNAT rule is enabled / disabled + #: *true:* SNAT rule is enabled + #: *false:* SNAT rule is disabled + status = resource.Body('status') diff --git a/otcextensions/tests/functional/osclient/nat/v2/test_dnat_rule.py b/otcextensions/tests/functional/osclient/nat/v2/test_dnat_rule.py index 837f2f319..724a6deac 100644 --- a/otcextensions/tests/functional/osclient/nat/v2/test_dnat_rule.py +++ b/otcextensions/tests/functional/osclient/nat/v2/test_dnat_rule.py @@ -60,14 +60,15 @@ def test_03_nat_dnat_rule_create(self): self.assertIsNotNone(self.PORT_ID) self.assertIsNotNone(self.FLOATING_IP_ID) json_output = json.loads(self.openstack( - 'nat dnat rule create ' - '{nat_id} {floating_ip_id} ' - '--protocol TCP ' + 'nat dnat rule create {nat_gateway_id} ' + '--floating-ip-id {floating_ip_id} ' + '--protocol {protocol} ' '--internal-service-port 80 ' '--external-service-port 80 ' '--private-ip {private_ip} ' '-f json'.format( - nat_id=self.NAT_ID, + nat_gateway_id=self.NAT_ID, + protocol='TCP', private_ip='192.168.0.3', floating_ip_id=self.FLOATING_IP_ID) )) diff --git a/otcextensions/tests/functional/osclient/nat/v2/test_nat_gateway.py b/otcextensions/tests/functional/osclient/nat/v2/test_nat_gateway.py index 9d861e034..f9d82a7d5 100644 --- a/otcextensions/tests/functional/osclient/nat/v2/test_nat_gateway.py +++ b/otcextensions/tests/functional/osclient/nat/v2/test_nat_gateway.py @@ -38,10 +38,11 @@ def test_02_gat_gateway_list_filters(self): self.openstack( 'nat gateway list ' '--limit 1 --id 2 ' - '--name 3 --spec 1 ' - '--router-id 123asd ' - '--internal-network-id 123qwe ' - '--status Active ' + '--name 3 --spec 4 ' + '--router-id 5 ' + '--internal-network-id 6 ' + '--project-id 7 ' + '--status active ' '--admin-state-up True ' ) diff --git a/otcextensions/tests/functional/osclient/nat/v2/test_snat_rule.py b/otcextensions/tests/functional/osclient/nat/v2/test_snat_rule.py index 4460f6235..dddc3fac1 100644 --- a/otcextensions/tests/functional/osclient/nat/v2/test_snat_rule.py +++ b/otcextensions/tests/functional/osclient/nat/v2/test_snat_rule.py @@ -57,10 +57,10 @@ def test_03_nat_snat_rule_create(self): self.assertIsNotNone(self.NAT_ID) self.assertIsNotNone(self.FLOATING_IP_ID) json_output = json.loads(self.openstack( - 'nat snat rule create ' - '{nat_id} {floating_ip_id} ' + 'nat snat rule create {nat_gateway_id} ' + '--floating-ip-id {floating_ip_id} ' '--net-id {net_id} -f json'.format( - nat_id=self.NAT_ID, + nat_gateway_id=self.NAT_ID, floating_ip_id=self.FLOATING_IP_ID, net_id=self.NET_ID) )) @@ -115,11 +115,11 @@ def test_08_nat_snat_rule_create_cidr_source_type(self): self.assertIsNotNone(self.NAT_ID) self.assertIsNotNone(self.FLOATING_IP_ID) json_output = json.loads(self.openstack( - 'nat snat rule create ' - '{nat_id} {floating_ip_id} ' + 'nat snat rule create {nat_gateway_id} ' + '--floating-ip-id {floating_ip_id} ' '--source-type {source_type} ' '--cidr {cidr} -f json'.format( - nat_id=self.NAT_ID, + nat_gateway_id=self.NAT_ID, floating_ip_id=self.FLOATING_IP_ID, source_type=1, cidr='192.168.5.0/24') diff --git a/otcextensions/tests/unit/osclient/nat/v2/test_dnat.py b/otcextensions/tests/unit/osclient/nat/v2/test_dnat.py index f363ccd9a..71070da7f 100644 --- a/otcextensions/tests/unit/osclient/nat/v2/test_dnat.py +++ b/otcextensions/tests/unit/osclient/nat/v2/test_dnat.py @@ -99,7 +99,7 @@ def test_list_args(self): ('limit', 1), ('id', '2'), ('nat_gateway_id', '3'), - ('tenant_id', '4'), + ('project_id', '4'), ('private_ip', '5'), ('internal_service_port', '6'), ('protocol', '7'), @@ -123,7 +123,7 @@ def test_list_args(self): limit=1, id='2', nat_gateway_id='3', - tenant_id='4', + project_id='4', private_ip='5', internal_service_port='6', protocol='7', diff --git a/otcextensions/tests/unit/osclient/nat/v2/test_gateway.py b/otcextensions/tests/unit/osclient/nat/v2/test_gateway.py index 4dafce406..ecf54c901 100644 --- a/otcextensions/tests/unit/osclient/nat/v2/test_gateway.py +++ b/otcextensions/tests/unit/osclient/nat/v2/test_gateway.py @@ -75,7 +75,7 @@ def test_list_args(self): ('limit', 1), ('id', '2'), ('name', '3'), - ('tenant_id', '4'), + ('project_id', '4'), ('spec', '5'), ('router_id', '6'), ('internal_network_id', '7'), @@ -97,7 +97,7 @@ def test_list_args(self): limit=1, id='2', name='3', - tenant_id='4', + project_id='4', spec='5', router_id='6', internal_network_id='7', diff --git a/otcextensions/tests/unit/osclient/nat/v2/test_snat.py b/otcextensions/tests/unit/osclient/nat/v2/test_snat.py index a9b739b8d..b75f5a8f3 100644 --- a/otcextensions/tests/unit/osclient/nat/v2/test_snat.py +++ b/otcextensions/tests/unit/osclient/nat/v2/test_snat.py @@ -97,7 +97,7 @@ def test_list_args(self): ('id', '2'), ('nat_gateway_id', '3'), ('network_id', '4'), - ('tenant_id', '5'), + ('project_id', '5'), ('cidr', '6'), ('source_type', '7'), ('floating_ip_id', '8'), @@ -121,7 +121,7 @@ def test_list_args(self): id='2', nat_gateway_id='3', network_id='4', - tenant_id='5', + project_id='5', cidr='6', source_type='7', floating_ip_id='8', From 0d022ed739f3e0ea96ab920894d941401c4768ee Mon Sep 17 00:00:00 2001 From: Vineet Pruthi Date: Mon, 16 Mar 2020 07:58:37 +0000 Subject: [PATCH 26/73] Updated nat_gateway_id as keyword arg --- otcextensions/osclient/nat/v2/dnat.py | 3 ++- otcextensions/osclient/nat/v2/snat.py | 3 ++- .../tests/functional/osclient/nat/v2/test_dnat_rule.py | 3 ++- .../tests/functional/osclient/nat/v2/test_snat_rule.py | 6 ++++-- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/otcextensions/osclient/nat/v2/dnat.py b/otcextensions/osclient/nat/v2/dnat.py index 2254e4b8a..0b9427ad3 100644 --- a/otcextensions/osclient/nat/v2/dnat.py +++ b/otcextensions/osclient/nat/v2/dnat.py @@ -169,7 +169,8 @@ class CreateDnatRule(command.ShowOne): def get_parser(self, prog_name): parser = super(CreateDnatRule, self).get_parser(prog_name) parser.add_argument( - 'nat_gateway_id', + '--nat-gateway-id', + required=True, metavar="", help=_("Specifies the ID of the NAT gateway")) parser.add_argument( diff --git a/otcextensions/osclient/nat/v2/snat.py b/otcextensions/osclient/nat/v2/snat.py index 76f52ac06..1fe8a41b0 100644 --- a/otcextensions/osclient/nat/v2/snat.py +++ b/otcextensions/osclient/nat/v2/snat.py @@ -158,7 +158,8 @@ class CreateSnatRule(command.ShowOne): def get_parser(self, prog_name): parser = super(CreateSnatRule, self).get_parser(prog_name) parser.add_argument( - 'nat_gateway_id', + '--nat-gateway-id', + required=True, metavar='', help=_('Specifies the ID of the NAT gateway')) parser.add_argument( diff --git a/otcextensions/tests/functional/osclient/nat/v2/test_dnat_rule.py b/otcextensions/tests/functional/osclient/nat/v2/test_dnat_rule.py index 724a6deac..71a106493 100644 --- a/otcextensions/tests/functional/osclient/nat/v2/test_dnat_rule.py +++ b/otcextensions/tests/functional/osclient/nat/v2/test_dnat_rule.py @@ -60,7 +60,8 @@ def test_03_nat_dnat_rule_create(self): self.assertIsNotNone(self.PORT_ID) self.assertIsNotNone(self.FLOATING_IP_ID) json_output = json.loads(self.openstack( - 'nat dnat rule create {nat_gateway_id} ' + 'nat dnat rule create ' + '--nat-gateway-id {nat_gateway_id} ' '--floating-ip-id {floating_ip_id} ' '--protocol {protocol} ' '--internal-service-port 80 ' diff --git a/otcextensions/tests/functional/osclient/nat/v2/test_snat_rule.py b/otcextensions/tests/functional/osclient/nat/v2/test_snat_rule.py index dddc3fac1..638372b0e 100644 --- a/otcextensions/tests/functional/osclient/nat/v2/test_snat_rule.py +++ b/otcextensions/tests/functional/osclient/nat/v2/test_snat_rule.py @@ -57,7 +57,8 @@ def test_03_nat_snat_rule_create(self): self.assertIsNotNone(self.NAT_ID) self.assertIsNotNone(self.FLOATING_IP_ID) json_output = json.loads(self.openstack( - 'nat snat rule create {nat_gateway_id} ' + 'nat snat rule create ' + '--nat-gateway-id {nat_gateway_id} ' '--floating-ip-id {floating_ip_id} ' '--net-id {net_id} -f json'.format( nat_gateway_id=self.NAT_ID, @@ -115,7 +116,8 @@ def test_08_nat_snat_rule_create_cidr_source_type(self): self.assertIsNotNone(self.NAT_ID) self.assertIsNotNone(self.FLOATING_IP_ID) json_output = json.loads(self.openstack( - 'nat snat rule create {nat_gateway_id} ' + 'nat snat rule create ' + '--nat-gateway-id {nat_gateway_id} ' '--floating-ip-id {floating_ip_id} ' '--source-type {source_type} ' '--cidr {cidr} -f json'.format( From 253c3eea8eafd7f64a3300267c93224e2b528ecd Mon Sep 17 00:00:00 2001 From: Vineet Pruthi Date: Wed, 18 Mar 2020 08:46:08 +0000 Subject: [PATCH 27/73] remove python2 dependancy from tox --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index 28b0062a1..e450963fe 100644 --- a/tox.ini +++ b/tox.ini @@ -1,6 +1,6 @@ [tox] minversion = 3.1 -envlist = py27,py36,py37,pep8 +envlist = py36,py37,pep8 skipsdist = True ignore_basepython_conflict = True From 5f561c9430a3366733eb397bd860b181b2609fba Mon Sep 17 00:00:00 2001 From: Vineet Pruthi Date: Wed, 18 Mar 2020 09:58:36 +0000 Subject: [PATCH 28/73] Updated args for show delete and update for NAT --- otcextensions/osclient/nat/v2/dnat.py | 12 ++++++------ otcextensions/osclient/nat/v2/gateway.py | 18 +++++++++--------- otcextensions/osclient/nat/v2/snat.py | 12 ++++++------ 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/otcextensions/osclient/nat/v2/dnat.py b/otcextensions/osclient/nat/v2/dnat.py index 0b9427ad3..e41a8c7fa 100644 --- a/otcextensions/osclient/nat/v2/dnat.py +++ b/otcextensions/osclient/nat/v2/dnat.py @@ -147,15 +147,15 @@ class ShowDnatRule(command.ShowOne): def get_parser(self, prog_name): parser = super(ShowDnatRule, self).get_parser(prog_name) parser.add_argument( - 'dnat_rule_id', - metavar='', + 'dnat', + metavar='', help=_('Specifies the ID of the SNAT Rule'), ) return parser def take_action(self, parsed_args): client = self.app.client_manager.nat - obj = client.get_dnat_rule(parsed_args.dnat_rule_id) + obj = client.get_dnat_rule(parsed_args.dnat) display_columns, columns = _get_columns(obj) data = utils.get_item_properties(obj, columns) @@ -239,8 +239,8 @@ class DeleteDnatRule(command.Command): def get_parser(self, prog_name): parser = super(DeleteDnatRule, self).get_parser(prog_name) parser.add_argument( - 'dnat_rule_id', - metavar='', + 'dnat', + metavar='', help=_('Specifies the ID of the DNAT Rule'), ) @@ -248,5 +248,5 @@ def get_parser(self, prog_name): def take_action(self, parsed_args): client = self.app.client_manager.nat - dnat_rule = client.get_dnat_rule(parsed_args.dnat_rule_id) + dnat_rule = client.get_dnat_rule(parsed_args.dnat) client.delete_dnat_rule(dnat_rule.id) diff --git a/otcextensions/osclient/nat/v2/gateway.py b/otcextensions/osclient/nat/v2/gateway.py index a12c033ab..c402c162b 100644 --- a/otcextensions/osclient/nat/v2/gateway.py +++ b/otcextensions/osclient/nat/v2/gateway.py @@ -113,15 +113,15 @@ class ShowNatGateway(command.ShowOne): def get_parser(self, prog_name): parser = super(ShowNatGateway, self).get_parser(prog_name) parser.add_argument( - 'nat_gateway', - metavar='', + 'gateway', + metavar='', help=_('Specifies the ID of the NAT Gateway.'), ) return parser def take_action(self, parsed_args): client = self.app.client_manager.nat - obj = client.find_gateway(parsed_args.nat_gateway) + obj = client.find_gateway(parsed_args.gateway) display_columns, columns = _get_columns(obj) data = utils.get_item_properties(obj, columns) @@ -195,8 +195,8 @@ class UpdateNatGateway(command.ShowOne): def get_parser(self, prog_name): parser = super(UpdateNatGateway, self).get_parser(prog_name) parser.add_argument( - 'nat_gateway', - metavar='', + 'gateway', + metavar='', help=_('Specifies the Name or ID of the NAT Gateway.'), ) parser.add_argument( @@ -222,7 +222,7 @@ def take_action(self, parsed_args): for arg in args_list: if getattr(parsed_args, arg): attrs[arg] = getattr(parsed_args, arg) - nat_gateway = client.find_gateway(parsed_args.nat_gateway) + nat_gateway = client.find_gateway(parsed_args.gateway) obj = client.update_gateway(nat_gateway.id, **attrs) @@ -239,8 +239,8 @@ class DeleteNatGateway(command.Command): def get_parser(self, prog_name): parser = super(DeleteNatGateway, self).get_parser(prog_name) parser.add_argument( - 'nat_gateway', - metavar='', + 'gateway', + metavar='', help=_('Specifies the Name or ID of the NAT gateway.'), ) @@ -248,5 +248,5 @@ def get_parser(self, prog_name): def take_action(self, parsed_args): client = self.app.client_manager.nat - nat_gateway = client.find_gateway(parsed_args.nat_gateway) + nat_gateway = client.find_gateway(parsed_args.gateway) client.delete_gateway(nat_gateway.id) diff --git a/otcextensions/osclient/nat/v2/snat.py b/otcextensions/osclient/nat/v2/snat.py index 1fe8a41b0..effd08be3 100644 --- a/otcextensions/osclient/nat/v2/snat.py +++ b/otcextensions/osclient/nat/v2/snat.py @@ -136,15 +136,15 @@ class ShowSnatRule(command.ShowOne): def get_parser(self, prog_name): parser = super(ShowSnatRule, self).get_parser(prog_name) parser.add_argument( - 'snat_rule_id', - metavar='', + 'snat', + metavar='', help=_('Specifies the ID of the SNAT Rule'), ) return parser def take_action(self, parsed_args): client = self.app.client_manager.nat - obj = client.get_snat_rule(parsed_args.snat_rule_id) + obj = client.get_snat_rule(parsed_args.snat) display_columns, columns = _get_columns(obj) data = utils.get_item_properties(obj, columns) @@ -221,8 +221,8 @@ class DeleteSnatRule(command.Command): def get_parser(self, prog_name): parser = super(DeleteSnatRule, self).get_parser(prog_name) parser.add_argument( - 'snat_rule_id', - metavar='', + 'snat', + metavar='', help=_('Specifies the ID of the SNAT Rule'), ) @@ -230,5 +230,5 @@ def get_parser(self, prog_name): def take_action(self, parsed_args): client = self.app.client_manager.nat - snat_rule = client.get_snat_rule(parsed_args.snat_rule_id) + snat_rule = client.get_snat_rule(parsed_args.snat) client.delete_snat_rule(snat_rule.id) From 5a6be533e3f968b7029139951e943a0a4bff54f8 Mon Sep 17 00:00:00 2001 From: Vineet Pruthi Date: Wed, 18 Mar 2020 10:04:26 +0000 Subject: [PATCH 29/73] Updated travis.yml to skip py27 and include py37 --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 0cfad8233..2e6a49ecd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,8 @@ matrix: include: - python: 3.6 env: TOXENV=py36 + - python: 3.7 + env: TOXENV=py37 - python: 3.6 env: TOXENV=pep8 install: pip install tox From 4b7d7f02477218109bf186a5a425bb842e53f96b Mon Sep 17 00:00:00 2001 From: Vineet Pruthi Date: Wed, 18 Mar 2020 10:11:31 +0000 Subject: [PATCH 30/73] Fixed unit tests with updated args --- otcextensions/tests/unit/osclient/nat/v2/test_dnat.py | 4 ++-- otcextensions/tests/unit/osclient/nat/v2/test_gateway.py | 4 ++-- otcextensions/tests/unit/osclient/nat/v2/test_snat.py | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/otcextensions/tests/unit/osclient/nat/v2/test_dnat.py b/otcextensions/tests/unit/osclient/nat/v2/test_dnat.py index 71070da7f..96cdce9b9 100644 --- a/otcextensions/tests/unit/osclient/nat/v2/test_dnat.py +++ b/otcextensions/tests/unit/osclient/nat/v2/test_dnat.py @@ -170,7 +170,7 @@ def test_show(self): ] verifylist = [ - ('dnat_rule_id', 'test_dnat_rule_id'), + ('dnat', 'test_dnat_rule_id'), ] # Verify cm is triggered with default parameters @@ -202,7 +202,7 @@ def test_delete(self): ] verifylist = [ - ('dnat_rule_id', 'test_dnat_rule_id'), + ('dnat', 'test_dnat_rule_id'), ] # Verify cm is triggered with default parameters diff --git a/otcextensions/tests/unit/osclient/nat/v2/test_gateway.py b/otcextensions/tests/unit/osclient/nat/v2/test_gateway.py index ecf54c901..5bec40554 100644 --- a/otcextensions/tests/unit/osclient/nat/v2/test_gateway.py +++ b/otcextensions/tests/unit/osclient/nat/v2/test_gateway.py @@ -139,7 +139,7 @@ def test_show(self): ] verifylist = [ - ('nat_gateway', 'test_gateway'), + ('gateway', 'test_gateway'), ] # Verify cm is triggered with default parameters @@ -171,7 +171,7 @@ def test_delete(self): ] verifylist = [ - ('nat_gateway', 'test_gateway'), + ('gateway', 'test_gateway'), ] # Verify cm is triggered with default parameters diff --git a/otcextensions/tests/unit/osclient/nat/v2/test_snat.py b/otcextensions/tests/unit/osclient/nat/v2/test_snat.py index b75f5a8f3..c9bcef99d 100644 --- a/otcextensions/tests/unit/osclient/nat/v2/test_snat.py +++ b/otcextensions/tests/unit/osclient/nat/v2/test_snat.py @@ -165,7 +165,7 @@ def test_show(self): ] verifylist = [ - ('snat_rule_id', 'test_snat_rule_id'), + ('snat', 'test_snat_rule_id'), ] # Verify cm is triggered with default parameters @@ -197,7 +197,7 @@ def test_delete(self): ] verifylist = [ - ('snat_rule_id', 'test_snat_rule_id'), + ('snat', 'test_snat_rule_id'), ] # Verify cm is triggered with default parameters From fe0ac5dc9f3b778277396482690e7b189e2d7eba Mon Sep 17 00:00:00 2001 From: Vineet Pruthi Date: Wed, 18 Mar 2020 10:25:21 +0000 Subject: [PATCH 31/73] roll back py27 in tox.ini --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index e450963fe..28b0062a1 100644 --- a/tox.ini +++ b/tox.ini @@ -1,6 +1,6 @@ [tox] minversion = 3.1 -envlist = py36,py37,pep8 +envlist = py27,py36,py37,pep8 skipsdist = True ignore_basepython_conflict = True From ed9c3af1822968689f820e2eef641c0b175ebe0a Mon Sep 17 00:00:00 2001 From: Vineet Pruthi Date: Thu, 19 Mar 2020 08:44:53 +0000 Subject: [PATCH 32/73] Fixed errors and remove nat documentation" --- doc/source/cli/index.rst | 1 - doc/source/cli/nat.rst | 36 ------ doc/source/enforcer.py | 1 - doc/source/user/guides/nat.rst | 4 - doc/source/user/proxies/nat_v2.rst | 48 -------- doc/source/user/resources/nat/index.rst | 9 -- doc/source/user/resources/nat/v2/dnat.rst | 13 --- doc/source/user/resources/nat/v2/gateway.rst | 13 --- doc/source/user/resources/nat/v2/snat.rst | 13 --- otcextensions/osclient/nat/v2/snat.py | 3 +- otcextensions/sdk/nat/v2/dnat.py | 9 +- .../osclient/nat/v2/test_dnat_rule.py | 18 +-- .../osclient/nat/v2/test_nat_gateway.py | 20 ++-- .../osclient/nat/v2/test_snat_rule.py | 31 ++--- .../tests/unit/osclient/nat/v2/test_dnat.py | 65 +++++++++++ .../unit/osclient/nat/v2/test_gateway.py | 110 ++++++++++++++++++ .../tests/unit/osclient/nat/v2/test_snat.py | 54 +++++++++ 17 files changed, 271 insertions(+), 177 deletions(-) delete mode 100644 doc/source/cli/nat.rst delete mode 100644 doc/source/user/guides/nat.rst delete mode 100644 doc/source/user/proxies/nat_v2.rst delete mode 100644 doc/source/user/resources/nat/index.rst delete mode 100644 doc/source/user/resources/nat/v2/dnat.rst delete mode 100644 doc/source/user/resources/nat/v2/gateway.rst delete mode 100644 doc/source/user/resources/nat/v2/snat.rst diff --git a/doc/source/cli/index.rst b/doc/source/cli/index.rst index 02343465b..524564ba6 100644 --- a/doc/source/cli/index.rst +++ b/doc/source/cli/index.rst @@ -14,7 +14,6 @@ OpenStackClient CLI Usage dns.rst rds.rst kms.rst - nat.rst load_balancer.rst obs.rst volume_backup.rst diff --git a/doc/source/cli/nat.rst b/doc/source/cli/nat.rst deleted file mode 100644 index 96b1fe5ae..000000000 --- a/doc/source/cli/nat.rst +++ /dev/null @@ -1,36 +0,0 @@ -===================================================== -Network Address Translation (nat) command-line client -===================================================== - -The NAT client is the command-line interface (CLI) for -the Database service (NAT) API and its extensions. - -For help on a specific `nat` command, enter: - -.. code-block:: console - - $ openstack nat help SUBCOMMAND - -.. _gateway: - -NAT Gateway operations ----------------------- - -.. autoprogram-cliff:: openstack.nat.v2 - :command: nat gateway * - -.. _snat: - -SNAT Rule operations --------------------- - -.. autoprogram-cliff:: openstack.nat.v2 - :command: nat snat * - -.. _dnat: - -DNAT Rule operations --------------------- - -.. autoprogram-cliff:: openstack.nat.v2 - :command: nat dnat * diff --git a/doc/source/enforcer.py b/doc/source/enforcer.py index 87f472bce..7c6d46953 100644 --- a/doc/source/enforcer.py +++ b/doc/source/enforcer.py @@ -50,7 +50,6 @@ def get_proxy_methods(): "otcextensions.sdk.obs.v1._proxy", "otcextensions.sdk.rds.v1._proxy", "otcextensions.sdk.rds.v3._proxy", - "otcextensions.sdk.nat.v2._proxy", "otcextensions.sdk.volume_backup.v2._proxy" ] diff --git a/doc/source/user/guides/nat.rst b/doc/source/user/guides/nat.rst deleted file mode 100644 index 8553150ba..000000000 --- a/doc/source/user/guides/nat.rst +++ /dev/null @@ -1,4 +0,0 @@ -Using OTC NAT -============= - -.. TODO(agoncharov): Implement this guide diff --git a/doc/source/user/proxies/nat_v2.rst b/doc/source/user/proxies/nat_v2.rst deleted file mode 100644 index 7ec2c4df3..000000000 --- a/doc/source/user/proxies/nat_v2.rst +++ /dev/null @@ -1,48 +0,0 @@ -Database NAT API -================ - -For details on how to use database, see :doc:`/user/guides/rds` - -.. automodule:: otcextensions.sdk.nat.v2._proxy - -The NAT Class --------------- - -The NAT high-level interface is available through the ``nat`` member of a -:class:`~openstack.connection.Connection` object. The ``nat`` member will only -be added if the ``otcextensions.sdk.register_otc_extensions(conn)`` method is -called. - -NAT Gateway Operations -^^^^^^^^^^^^^^^^^^^^^^ - -.. autoclass:: otcextensions.sdk.nat.v2._proxy.Proxy - - .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.create_gateway - .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.update_gateway - .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.delete_gateway - .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.get_gateway - .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.find_gateway - .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.gateways - - -NAT Snat Rule Operations -^^^^^^^^^^^^^^^^^^^^^^^^ - -.. autoclass:: otcextensions.sdk.nat.v2._proxy.Proxy - - .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.create_snat_rule - .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.delete_snat_rule - .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.get_snat_rule - .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.delete_snat_rule - - -NAT Dnat Rule Operations -^^^^^^^^^^^^^^^^^^^^^^^^ - -.. autoclass:: otcextensions.sdk.nat.v2._proxy.Proxy - - .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.create_dnat_rule - .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.delete_dnat_rule - .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.get_dnat_rule - .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.delete_dnat_rule diff --git a/doc/source/user/resources/nat/index.rst b/doc/source/user/resources/nat/index.rst deleted file mode 100644 index 712e949da..000000000 --- a/doc/source/user/resources/nat/index.rst +++ /dev/null @@ -1,9 +0,0 @@ -NAT Resources -============= - -.. toctree:: - :maxdepth: 1 - - v2/gateway - v2/snat - v2/dnat diff --git a/doc/source/user/resources/nat/v2/dnat.rst b/doc/source/user/resources/nat/v2/dnat.rst deleted file mode 100644 index 6b26243ee..000000000 --- a/doc/source/user/resources/nat/v2/dnat.rst +++ /dev/null @@ -1,13 +0,0 @@ -otcextensions.sdk.nat.v2.dnat -============================= - -.. automodule:: otcextensions.sdk.nat.v2.dnat - -The Dnat Class --------------- - -The ``Dnat`` class inherits from -:class:`~otcextensions.sdk.sdk_resource.Resource`. - -.. autoclass:: otcextensions.sdk.nat.v2.dnat.Dnat - :members: diff --git a/doc/source/user/resources/nat/v2/gateway.rst b/doc/source/user/resources/nat/v2/gateway.rst deleted file mode 100644 index 8d30e9838..000000000 --- a/doc/source/user/resources/nat/v2/gateway.rst +++ /dev/null @@ -1,13 +0,0 @@ -otcextensions.sdk.nat.v2.gateway -================================ - -.. automodule:: otcextensions.sdk.nat.v2.gateway - -The Instance Class ------------------- - -The ``Gateway`` class inherits from -:class:`~otcextensions.sdk.sdk_resource.Resource`. - -.. autoclass:: otcextensions.sdk.nat.v2.gateway.Gateway - :members: diff --git a/doc/source/user/resources/nat/v2/snat.rst b/doc/source/user/resources/nat/v2/snat.rst deleted file mode 100644 index ea55439ee..000000000 --- a/doc/source/user/resources/nat/v2/snat.rst +++ /dev/null @@ -1,13 +0,0 @@ -otcextensions.sdk.nat.v2.snat -============================= - -.. automodule:: otcextensions.sdk.nat.v2.snat - -The Instance Class ------------------- - -The ``Dnat`` class inherits from -:class:`~otcextensions.sdk.sdk_resource.Resource`. - -.. autoclass:: otcextensions.sdk.nat.v2.snat.Snat - :members: diff --git a/otcextensions/osclient/nat/v2/snat.py b/otcextensions/osclient/nat/v2/snat.py index effd08be3..b22ef7293 100644 --- a/otcextensions/osclient/nat/v2/snat.py +++ b/otcextensions/osclient/nat/v2/snat.py @@ -169,9 +169,8 @@ def get_parser(self, prog_name): help=_('Specifies the EIP ID. Multiple EIPs ' 'are separated using commas')) parser.add_argument( - '--net-id', + '--network-id', metavar='', - dest='network_id', help=_('Specifies the network ID used by the SNAT rule. ' 'This parameter and cidr arealternative.')) parser.add_argument( diff --git a/otcextensions/sdk/nat/v2/dnat.py b/otcextensions/sdk/nat/v2/dnat.py index f03efea6a..4f1807189 100644 --- a/otcextensions/sdk/nat/v2/dnat.py +++ b/otcextensions/sdk/nat/v2/dnat.py @@ -24,11 +24,10 @@ class Dnat(resource.Resource): allow_list = True _query_mapping = resource.QueryParameters( - 'admin_state_up', 'cidr', 'created_at', 'external_service_port', - 'floating_ip_address', 'floating_ip_id', 'id', 'internal_service_port', - 'limit', 'nat_gateway_id', 'network_id', 'port_id', 'private_ip', - 'protocol', 'source_type', 'status', 'project_id', - project_id='tenant_id' + 'admin_state_up', 'created_at', 'external_service_port', 'id', + 'floating_ip_address', 'floating_ip_id', 'internal_service_port', + 'limit', 'nat_gateway_id', 'port_id', 'private_ip', 'protocol', + 'status', 'project_id', project_id='tenant_id' ) # Properties diff --git a/otcextensions/tests/functional/osclient/nat/v2/test_dnat_rule.py b/otcextensions/tests/functional/osclient/nat/v2/test_dnat_rule.py index 71a106493..6dc7c1de4 100644 --- a/otcextensions/tests/functional/osclient/nat/v2/test_dnat_rule.py +++ b/otcextensions/tests/functional/osclient/nat/v2/test_dnat_rule.py @@ -21,11 +21,11 @@ class TestDnatRule(base.TestCase): UUID = uuid.uuid4().hex[:8] ROUTER_NAME = 'sdk-test-router-' + UUID - NET_NAME = 'sdk-test-net-' + UUID + NETWORK_NAME = 'sdk-test-net-' + UUID SUBNET_NAME = 'sdk-test-subnet-' + UUID PORT_NAME = 'sdk-test-port-' + UUID ROUTER_ID = None - NET_ID = None + NETWORK_ID = None FLOATING_IP_ID = None PORT_ID = None @@ -122,7 +122,7 @@ def _create_nat_gateway(self): ' --spec {spec} -f json'.format( name=self.NAT_NAME, router_id=self.ROUTER_ID, - net_id=self.NET_ID, + net_id=self.NETWORK_ID, description='OTCE Lib Test', spec=1) )) @@ -136,15 +136,15 @@ def _initialize_network(self): router = json.loads(self.openstack( 'router create -f json ' + self.ROUTER_NAME )) - net = json.loads(self.openstack( - 'network create -f json ' + self.NET_NAME + network = json.loads(self.openstack( + 'network create -f json ' + self.NETWORK_NAME )) self.openstack( 'subnet create {subnet} -f json ' '--network {net} ' '--subnet-range 192.168.0.0/24 '.format( subnet=self.SUBNET_NAME, - net=self.NET_NAME + net=self.NETWORK_NAME )) self.openstack( @@ -162,7 +162,7 @@ def _initialize_network(self): )) TestDnatRule.ROUTER_ID = router['id'] - TestDnatRule.NET_ID = net['id'] + TestDnatRule.NETWORK_ID = network['id'] TestDnatRule.FLOATING_IP_ID = floating_ip['id'] port = json.loads(self.openstack( @@ -170,7 +170,7 @@ def _initialize_network(self): '--network {net_id} ' '-f json'.format( name=self.PORT_NAME, - net_id=self.NET_ID) + net_id=self.NETWORK_ID) )) TestDnatRule.PORT_ID = port['id'] @@ -189,7 +189,7 @@ def _denitialize_network(self): 'subnet delete ' + self.SUBNET_NAME ) self.openstack( - 'network delete ' + self.NET_NAME + 'network delete ' + self.NETWORK_NAME ) self.openstack( 'router delete ' + self.ROUTER_NAME diff --git a/otcextensions/tests/functional/osclient/nat/v2/test_nat_gateway.py b/otcextensions/tests/functional/osclient/nat/v2/test_nat_gateway.py index f9d82a7d5..a0f78e0a0 100644 --- a/otcextensions/tests/functional/osclient/nat/v2/test_nat_gateway.py +++ b/otcextensions/tests/functional/osclient/nat/v2/test_nat_gateway.py @@ -21,10 +21,10 @@ class TestNatGateway(base.TestCase): UUID = uuid.uuid4().hex[:8] ROUTER_NAME = 'sdk-test-router-' + UUID - NET_NAME = 'sdk-test-net-' + UUID + NETWORK_NAME = 'sdk-test-net-' + UUID SUBNET_NAME = 'sdk-test-subnet-' + UUID ROUTER_ID = None - NET_ID = None + NETWORK_ID = None NAT_NAME = 'os-cli-test-' + UUID NAT_ID = None @@ -55,7 +55,7 @@ def test_03_nat_gateway_create(self): ' --spec {spec} -f json'.format( name=self.NAT_NAME, router_id=self.ROUTER_ID, - net_id=self.NET_ID, + net_id=self.NETWORK_ID, description='OTCE Lib Test', spec=1) )) @@ -119,6 +119,7 @@ def test_09_nat_gateway_update_by_id(self): def test_10_nat_gateway_update_by_name(self): name = 'os-cli-test-' + self.UUID description = "otce cli test nat" + spec = '2' json_output = json.loads(self.openstack( 'nat gateway update {nat_name} ' '--name {name} ' @@ -127,11 +128,12 @@ def test_10_nat_gateway_update_by_name(self): '-f json'.format( nat_name=self.NAT_NAME, name=name, - spec=2, + spec=spec, desc=description) )) self.assertEqual(json_output['name'], name) self.assertEqual(json_output['description'], description) + self.assertEqual(json_output['spec'], spec) TestNatGateway.NAT_NAME = json_output['name'] def test_11_nat_gateway_delete(self): @@ -142,15 +144,15 @@ def _initialize_network(self): router = json.loads(self.openstack( 'router create -f json ' + self.ROUTER_NAME )) - net = json.loads(self.openstack( - 'network create -f json ' + self.NET_NAME + network = json.loads(self.openstack( + 'network create -f json ' + self.NETWORK_NAME )) self.openstack( 'subnet create {subnet} -f json ' '--network {net} ' '--subnet-range 192.168.0.0/24 '.format( subnet=self.SUBNET_NAME, - net=self.NET_NAME + net=self.NETWORK_NAME )) self.openstack( @@ -162,7 +164,7 @@ def _initialize_network(self): ) TestNatGateway.ROUTER_ID = router['id'] - TestNatGateway.NET_ID = net['id'] + TestNatGateway.NETWORK_ID = network['id'] def _denitialize_network(self): self.openstack( @@ -176,7 +178,7 @@ def _denitialize_network(self): 'subnet delete ' + self.SUBNET_NAME ) self.openstack( - 'network delete ' + self.NET_NAME + 'network delete ' + self.NETWORK_NAME ) self.openstack( 'router delete ' + self.ROUTER_NAME diff --git a/otcextensions/tests/functional/osclient/nat/v2/test_snat_rule.py b/otcextensions/tests/functional/osclient/nat/v2/test_snat_rule.py index 638372b0e..7b46cc1d0 100644 --- a/otcextensions/tests/functional/osclient/nat/v2/test_snat_rule.py +++ b/otcextensions/tests/functional/osclient/nat/v2/test_snat_rule.py @@ -22,10 +22,10 @@ class TestSnatRule(base.TestCase): UUID = uuid.uuid4().hex[:8] ROUTER_NAME = 'sdk-test-router-' + UUID - NET_NAME = 'sdk-test-net-' + UUID + NETWORK_NAME = 'sdk-test-net-' + UUID SUBNET_NAME = 'sdk-test-subnet-' + UUID ROUTER_ID = None - NET_ID = None + NETWORK_ID = None FLOATING_IP_ID = None NAT_NAME = 'os-cli-test-' + UUID @@ -60,10 +60,10 @@ def test_03_nat_snat_rule_create(self): 'nat snat rule create ' '--nat-gateway-id {nat_gateway_id} ' '--floating-ip-id {floating_ip_id} ' - '--net-id {net_id} -f json'.format( + '--network-id {net_id} -f json'.format( nat_gateway_id=self.NAT_ID, floating_ip_id=self.FLOATING_IP_ID, - net_id=self.NET_ID) + net_id=self.NETWORK_ID) )) self.assertIsNotNone(json_output) TestSnatRule.SNAT_RULE_ID = json_output['id'] @@ -106,15 +106,17 @@ def test_07_nat_snat_rule_create_for_existing_network(self): self.openstack, 'nat snat rule create ' '{nat_id} {floating_ip_id} ' - '--net-id {net_id} -f json'.format( + '--network-id {net_id} -f json'.format( nat_id=self.NAT_ID, floating_ip_id=self.FLOATING_IP_ID, - net_id=self.NET_ID) + net_id=self.NETWORK_ID) ) def test_08_nat_snat_rule_create_cidr_source_type(self): self.assertIsNotNone(self.NAT_ID) self.assertIsNotNone(self.FLOATING_IP_ID) + cidr = '192.168.5.0/24' + source_type = 1 json_output = json.loads(self.openstack( 'nat snat rule create ' '--nat-gateway-id {nat_gateway_id} ' @@ -123,10 +125,11 @@ def test_08_nat_snat_rule_create_cidr_source_type(self): '--cidr {cidr} -f json'.format( nat_gateway_id=self.NAT_ID, floating_ip_id=self.FLOATING_IP_ID, - source_type=1, - cidr='192.168.5.0/24') + source_type=source_type, + cidr=cidr) )) - self.assertEqual(json_output['source_type'], 1) + self.assertEqual(json_output['source_type'], source_type) + self.assertEqual(json_output['cidr'], cidr) self.openstack( 'nat snat rule delete ' + json_output['id']) @@ -146,7 +149,7 @@ def _create_nat_gateway(self): ' --spec {spec} -f json'.format( name=self.NAT_NAME, router_id=self.ROUTER_ID, - net_id=self.NET_ID, + net_id=self.NETWORK_ID, description='OTCE Lib Test', spec=1) )) @@ -161,14 +164,14 @@ def _initialize_network(self): 'router create -f json ' + self.ROUTER_NAME )) net = json.loads(self.openstack( - 'network create -f json ' + self.NET_NAME + 'network create -f json ' + self.NETWORK_NAME )) self.openstack( 'subnet create {subnet} -f json ' '--network {net} ' '--subnet-range 192.168.0.0/24 '.format( subnet=self.SUBNET_NAME, - net=self.NET_NAME + net=self.NETWORK_NAME )) self.openstack( @@ -186,7 +189,7 @@ def _initialize_network(self): )) TestSnatRule.ROUTER_ID = router['id'] - TestSnatRule.NET_ID = net['id'] + TestSnatRule.NETWORK_ID = net['id'] TestSnatRule.FLOATING_IP_ID = floating_ip['id'] def _denitialize_network(self): @@ -201,7 +204,7 @@ def _denitialize_network(self): 'subnet delete ' + self.SUBNET_NAME ) self.openstack( - 'network delete ' + self.NET_NAME + 'network delete ' + self.NETWORK_NAME ) self.openstack( 'router delete ' + self.ROUTER_NAME diff --git a/otcextensions/tests/unit/osclient/nat/v2/test_dnat.py b/otcextensions/tests/unit/osclient/nat/v2/test_dnat.py index 96cdce9b9..7ef4a7abc 100644 --- a/otcextensions/tests/unit/osclient/nat/v2/test_dnat.py +++ b/otcextensions/tests/unit/osclient/nat/v2/test_dnat.py @@ -184,6 +184,71 @@ def test_show(self): self.assertEqual(self.data, data) +class TestCreateDnatRule(fakes.TestNat): + + _data = fakes.FakeDnatRule.create_one() + + columns = ( + 'admin_state_up', + 'created_at', + 'external_service_port', + 'floating_ip_address', + 'floating_ip_id', + 'id', + 'internal_service_port', + 'nat_gateway_id', + 'port_id', + 'private_ip', + 'project_id', + 'protocol', + 'status' + ) + + data = fakes.gen_data(_data, columns) + + def setUp(self): + super(TestCreateDnatRule, self).setUp() + + self.cmd = dnat.CreateDnatRule(self.app, None) + + self.client.create_dnat_rule = mock.Mock(return_value=self._data) + + def test_create(self): + arglist = [ + '--nat-gateway-id', 'test-nat-uuid', + '--floating-ip-id', 'test-floating-ip-uuid', + '--protocol', 'tcp', + '--internal-service-port', '80', + '--external-service-port', '80', + '--private-ip', '192.168.0.99', + ] + + verifylist = [ + ('nat_gateway_id', 'test-nat-uuid'), + ('floating_ip_id', 'test-floating-ip-uuid'), + ('protocol', 'tcp'), + ('internal_service_port', '80'), + ('external_service_port', '80'), + ('private_ip', '192.168.0.99'), + ] + + # Verify cm is triggered with default parameters + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + # Trigger the action + columns, data = self.cmd.take_action(parsed_args) + self.client.create_dnat_rule.assert_called_with( + nat_gateway_id='test-nat-uuid', + floating_ip_id='test-floating-ip-uuid', + protocol='tcp', + internal_service_port='80', + external_service_port='80', + private_ip='192.168.0.99') + + self.assertEqual(self.columns, columns) + self.assertEqual(self.data, data) + + class TestDeleteDnatRule(fakes.TestNat): data = fakes.FakeDnatRule.create_one() diff --git a/otcextensions/tests/unit/osclient/nat/v2/test_gateway.py b/otcextensions/tests/unit/osclient/nat/v2/test_gateway.py index 5bec40554..dd8dbd52b 100644 --- a/otcextensions/tests/unit/osclient/nat/v2/test_gateway.py +++ b/otcextensions/tests/unit/osclient/nat/v2/test_gateway.py @@ -107,6 +107,116 @@ def test_list_args(self): ) +class TestCreateNatGateway(fakes.TestNat): + + _data = fakes.FakeNatGateway.create_one() + + columns = ( + 'admin_state_up', + 'created_at', + 'description', + 'id', + 'internal_network_id', + 'name', + 'project_id', + 'router_id', + 'spec', + 'status' + ) + + data = fakes.gen_data(_data, columns) + + def setUp(self): + super(TestCreateNatGateway, self).setUp() + + self.cmd = gateway.CreateNatGateway(self.app, None) + + self.client.create_gateway = mock.Mock(return_value=self._data) + + def test_create(self): + arglist = [ + 'test-gateway', + '--router-id', 'test-router-uuid', + '--internal-network-id', 'test-network-uuid', + '--spec', '1', + ] + verifylist = [ + ('name', 'test-gateway'), + ('router_id', 'test-router-uuid'), + ('internal_network_id', 'test-network-uuid'), + ('spec', '1'), + ] + # Verify cm is triggereg with default parameters + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + # Trigger the action + columns, data = self.cmd.take_action(parsed_args) + + self.client.create_gateway.assert_called_with( + name='test-gateway', + router_id='test-router-uuid', + internal_network_id='test-network-uuid', + spec='1' + ) + self.assertEqual(self.columns, columns) + + +class TestUpdateNatGateway(fakes.TestNat): + + _data = fakes.FakeNatGateway.create_one() + + columns = ( + 'admin_state_up', + 'created_at', + 'description', + 'id', + 'internal_network_id', + 'name', + 'project_id', + 'router_id', + 'spec', + 'status' + ) + + data = fakes.gen_data(_data, columns) + + def setUp(self): + super(TestUpdateNatGateway, self).setUp() + + self.cmd = gateway.UpdateNatGateway(self.app, None) + + self.client.find_gateway = mock.Mock(return_value=self._data) + self.client.update_gateway = mock.Mock(return_value=self._data) + + def test_update(self): + arglist = [ + 'test-gateway', + '--name', 'test-gateway-updated', + '--description', 'nat gateway updated', + '--spec', '2', + ] + verifylist = [ + ('gateway', 'test-gateway'), + ('name', 'test-gateway-updated'), + ('description', 'nat gateway updated'), + ('spec', '2'), + ] + # Verify cm is triggereg with default parameters + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + # Trigger the action + columns, data = self.cmd.take_action(parsed_args) + + self.client.find_gateway.assert_called_with('test-gateway') + self.client.update_gateway.assert_called_with( + self._data.id, + name='test-gateway-updated', + description='nat gateway updated', + spec='2' + ) + self.assertEqual(self.columns, columns) + + class TestShowNatGateway(fakes.TestNat): _data = fakes.FakeNatGateway.create_one() diff --git a/otcextensions/tests/unit/osclient/nat/v2/test_snat.py b/otcextensions/tests/unit/osclient/nat/v2/test_snat.py index c9bcef99d..fba0db940 100644 --- a/otcextensions/tests/unit/osclient/nat/v2/test_snat.py +++ b/otcextensions/tests/unit/osclient/nat/v2/test_snat.py @@ -132,6 +132,60 @@ def test_list_args(self): ) +class TestCreateSnatRule(fakes.TestNat): + + _data = fakes.FakeSnatRule.create_one() + + columns = ( + 'admin_state_up', + 'cidr', + 'created_at', + 'floating_ip_address', + 'floating_ip_id', + 'id', + 'nat_gateway_id', + 'network_id', + 'project_id', + 'source_type', + 'status' + ) + + data = fakes.gen_data(_data, columns) + + def setUp(self): + super(TestCreateSnatRule, self).setUp() + + self.cmd = snat.CreateSnatRule(self.app, None) + + self.client.create_snat_rule = mock.Mock(return_value=self._data) + + def test_create(self): + arglist = [ + '--nat-gateway-id', 'test-nat-uuid', + '--floating-ip-id', 'test-floating-ip-uuid', + '--network-id', 'test-network-uuid', + ] + + verifylist = [ + ('nat_gateway_id', 'test-nat-uuid'), + ('floating_ip_id', 'test-floating-ip-uuid'), + ('network_id', 'test-network-uuid'), + ] + + # Verify cm is triggered with default parameters + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + # Trigger the action + columns, data = self.cmd.take_action(parsed_args) + self.client.create_snat_rule.assert_called_with( + nat_gateway_id='test-nat-uuid', + floating_ip_id='test-floating-ip-uuid', + network_id='test-network-uuid') + + self.assertEqual(self.columns, columns) + self.assertEqual(self.data, data) + + class TestShowSnatRule(fakes.TestNat): _data = fakes.FakeSnatRule.create_one() From 0517d9e27a40297a152d81b8328e04f0a61802a5 Mon Sep 17 00:00:00 2001 From: Vineet Pruthi Date: Fri, 20 Mar 2020 07:09:42 +0000 Subject: [PATCH 33/73] Removed print --- otcextensions/sdk/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/otcextensions/sdk/__init__.py b/otcextensions/sdk/__init__.py index ec60383f8..8f318507d 100644 --- a/otcextensions/sdk/__init__.py +++ b/otcextensions/sdk/__init__.py @@ -259,7 +259,6 @@ def load(conn, **kwargs): if service['service_type'] in conn._proxies: del conn._proxies[service['service_type']] # attr = getattr(conn, service_name) - # print(hasattr(conn, service_name)) # delattr(conn, service['service_type']) sd = _get_descriptor(service_name) From 3fd73ff6342fb1199be10214fa9d19b0766aeba4 Mon Sep 17 00:00:00 2001 From: "T. Schreiber" Date: Tue, 12 Nov 2019 10:05:37 +0000 Subject: [PATCH 34/73] initial nat gateway branche --- otcextensions/sdk/nat/v2/nat_gateway.py | 54 +++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 otcextensions/sdk/nat/v2/nat_gateway.py diff --git a/otcextensions/sdk/nat/v2/nat_gateway.py b/otcextensions/sdk/nat/v2/nat_gateway.py new file mode 100644 index 000000000..d87da1924 --- /dev/null +++ b/otcextensions/sdk/nat/v2/nat_gateway.py @@ -0,0 +1,54 @@ +# 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. +from openstack import resource + +class NatGateway(resource.Resource): + resources_key = 'nat_gateways' + base_path = '/nat_gateways' + + # capabilities + allow_create = True + allow_delete = True + allow_list = True + #allow_get = True + + # Properties + #: Specifies the ID of the NAT gateway. + id = resource.Body('id') + #: Specifies the project ID + tenant_id = resource.Body('tenant_id') + #: Specifies the name of the NAT gateway. + #: Contains only digits, letters, underscores and hyphens + name = resource.Body('name') + #: Provides description of NAT Gateway + description = resource.Body('description') + #: Specifies the type of the NAT gateway. + #: *1:* small type, supports up to 10,000 SNAT connections + #: *2:* medium type, supports up to 50,000 SNAT connections + #: *3:* large type, supports up to 200,000 SNAT connections + #: *4:* extra-large type, supports up to 1,000,000 SNAT connections + spec = resource.Body('spec', type=int) + #: Specifies the router ID + router_id = resource.Body('router_id') + #: Specifies the network ID of the downstream interface + internal_network_id = resource.Body('internal_network_id') + #: Specifies the status + status = resource.Body('status') + #: Specifies whether GW is up or down + #: *true:* Gw is up + #: *false:* GW is down + admin_state_up = resource.Body('admin_state_up', type=bool) + #: Specifies when GW was is created + #: format is *yyyy-mm-dd hh:mm:ss* + created_at = resource.Body('created_at') + + From 93b54d72f05e7d00c6905f6254d0e247bb829fb6 Mon Sep 17 00:00:00 2001 From: "T. Schreiber" Date: Tue, 12 Nov 2019 14:03:38 +0000 Subject: [PATCH 35/73] added snat and dnat resource --- otcextensions/sdk/nat/v2/nat_gateway.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/otcextensions/sdk/nat/v2/nat_gateway.py b/otcextensions/sdk/nat/v2/nat_gateway.py index d87da1924..b33776bf7 100644 --- a/otcextensions/sdk/nat/v2/nat_gateway.py +++ b/otcextensions/sdk/nat/v2/nat_gateway.py @@ -17,10 +17,11 @@ class NatGateway(resource.Resource): # capabilities allow_create = True + allow_fetch = True + allow_commit = True allow_delete = True allow_list = True - #allow_get = True - + # Properties #: Specifies the ID of the NAT gateway. id = resource.Body('id') From 8cec08249288302f1294a1fe7f473f446d511b78 Mon Sep 17 00:00:00 2001 From: "T. Schreiber" Date: Fri, 15 Nov 2019 13:36:12 +0000 Subject: [PATCH 36/73] first running state --- otcextensions/sdk/nat/v2/nat_gateway.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/otcextensions/sdk/nat/v2/nat_gateway.py b/otcextensions/sdk/nat/v2/nat_gateway.py index b33776bf7..a7951d81c 100644 --- a/otcextensions/sdk/nat/v2/nat_gateway.py +++ b/otcextensions/sdk/nat/v2/nat_gateway.py @@ -13,6 +13,7 @@ class NatGateway(resource.Resource): resources_key = 'nat_gateways' + resource_key = 'nat_gateway' base_path = '/nat_gateways' # capabilities @@ -37,7 +38,7 @@ class NatGateway(resource.Resource): #: *2:* medium type, supports up to 50,000 SNAT connections #: *3:* large type, supports up to 200,000 SNAT connections #: *4:* extra-large type, supports up to 1,000,000 SNAT connections - spec = resource.Body('spec', type=int) + spec = resource.Body('spec') #: Specifies the router ID router_id = resource.Body('router_id') #: Specifies the network ID of the downstream interface From 74d1daceb8a6c5cc50a2eefb96e149cd9fc4b4aa Mon Sep 17 00:00:00 2001 From: "T. Schreiber" Date: Fri, 15 Nov 2019 15:07:14 +0000 Subject: [PATCH 37/73] gateway fixed --- otcextensions/sdk/nat/v2/gateway.py | 13 ++---- otcextensions/sdk/nat/v2/nat_gateway.py | 56 ------------------------- 2 files changed, 3 insertions(+), 66 deletions(-) delete mode 100644 otcextensions/sdk/nat/v2/nat_gateway.py diff --git a/otcextensions/sdk/nat/v2/gateway.py b/otcextensions/sdk/nat/v2/gateway.py index b93901ebb..cf5dc99f4 100644 --- a/otcextensions/sdk/nat/v2/gateway.py +++ b/otcextensions/sdk/nat/v2/gateway.py @@ -11,7 +11,6 @@ # under the License. from openstack import resource - class Gateway(resource.Resource): resources_key = 'nat_gateways' resource_key = 'nat_gateway' @@ -23,13 +22,7 @@ class Gateway(resource.Resource): allow_commit = True allow_delete = True allow_list = True - - _query_mapping = resource.QueryParameters( - 'admin_state_up', 'created_at', 'description', 'id', - 'internal_network_id', 'limit', 'name', 'router_id', - 'spec', 'status', 'project_id', project_id='tenant_id' - ) - + # Properties #: Specifies whether GW is up or down #: *true:* Gw is up @@ -47,8 +40,6 @@ class Gateway(resource.Resource): #: Specifies the name of the gateway. #: Contains only digits, letters, underscores and hyphens name = resource.Body('name') - #: Specifies the project ID - project_id = resource.Body('tenant_id') #: Specifies the router ID router_id = resource.Body('router_id') #: Specifies the type of the gateway. @@ -59,3 +50,5 @@ class Gateway(resource.Resource): spec = resource.Body('spec') #: Specifies the status status = resource.Body('status') + #: Specifies the project ID + tenant_id = resource.Body('tenant_id') \ No newline at end of file diff --git a/otcextensions/sdk/nat/v2/nat_gateway.py b/otcextensions/sdk/nat/v2/nat_gateway.py deleted file mode 100644 index a7951d81c..000000000 --- a/otcextensions/sdk/nat/v2/nat_gateway.py +++ /dev/null @@ -1,56 +0,0 @@ -# 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. -from openstack import resource - -class NatGateway(resource.Resource): - resources_key = 'nat_gateways' - resource_key = 'nat_gateway' - base_path = '/nat_gateways' - - # capabilities - allow_create = True - allow_fetch = True - allow_commit = True - allow_delete = True - allow_list = True - - # Properties - #: Specifies the ID of the NAT gateway. - id = resource.Body('id') - #: Specifies the project ID - tenant_id = resource.Body('tenant_id') - #: Specifies the name of the NAT gateway. - #: Contains only digits, letters, underscores and hyphens - name = resource.Body('name') - #: Provides description of NAT Gateway - description = resource.Body('description') - #: Specifies the type of the NAT gateway. - #: *1:* small type, supports up to 10,000 SNAT connections - #: *2:* medium type, supports up to 50,000 SNAT connections - #: *3:* large type, supports up to 200,000 SNAT connections - #: *4:* extra-large type, supports up to 1,000,000 SNAT connections - spec = resource.Body('spec') - #: Specifies the router ID - router_id = resource.Body('router_id') - #: Specifies the network ID of the downstream interface - internal_network_id = resource.Body('internal_network_id') - #: Specifies the status - status = resource.Body('status') - #: Specifies whether GW is up or down - #: *true:* Gw is up - #: *false:* GW is down - admin_state_up = resource.Body('admin_state_up', type=bool) - #: Specifies when GW was is created - #: format is *yyyy-mm-dd hh:mm:ss* - created_at = resource.Body('created_at') - - From 86ee3589d528963ba5526f57e08aa2c6e9e9ed5c Mon Sep 17 00:00:00 2001 From: "T. Schreiber" Date: Fri, 15 Nov 2019 15:22:44 +0000 Subject: [PATCH 38/73] linting corrections --- otcextensions/sdk/nat/v2/gateway.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/otcextensions/sdk/nat/v2/gateway.py b/otcextensions/sdk/nat/v2/gateway.py index cf5dc99f4..8080521f9 100644 --- a/otcextensions/sdk/nat/v2/gateway.py +++ b/otcextensions/sdk/nat/v2/gateway.py @@ -11,6 +11,7 @@ # under the License. from openstack import resource + class Gateway(resource.Resource): resources_key = 'nat_gateways' resource_key = 'nat_gateway' @@ -22,7 +23,7 @@ class Gateway(resource.Resource): allow_commit = True allow_delete = True allow_list = True - + # Properties #: Specifies whether GW is up or down #: *true:* Gw is up @@ -51,4 +52,4 @@ class Gateway(resource.Resource): #: Specifies the status status = resource.Body('status') #: Specifies the project ID - tenant_id = resource.Body('tenant_id') \ No newline at end of file + tenant_id = resource.Body('tenant_id') From 2b2fa0f0333ee9e72fc1cdc1d4d24a13b6d0a522 Mon Sep 17 00:00:00 2001 From: "T. Schreiber" Date: Mon, 18 Nov 2019 15:46:18 +0000 Subject: [PATCH 39/73] Minor changes, tested successfully --- otcextensions/sdk/nat/v2/gateway.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/otcextensions/sdk/nat/v2/gateway.py b/otcextensions/sdk/nat/v2/gateway.py index 8080521f9..0b42f1172 100644 --- a/otcextensions/sdk/nat/v2/gateway.py +++ b/otcextensions/sdk/nat/v2/gateway.py @@ -24,6 +24,12 @@ class Gateway(resource.Resource): allow_delete = True allow_list = True + _query_mapping = resource.QueryParameters( + 'admin_state_up', 'created_at', 'description', 'id', + 'internal_network_id', 'limit', 'name', 'router_id', + 'spec', 'status', 'tenant_id' + ) + # Properties #: Specifies whether GW is up or down #: *true:* Gw is up From 4a2cdf4f19dee3edf0215e03744e5a6475a8d482 Mon Sep 17 00:00:00 2001 From: "T. Schreiber" Date: Fri, 6 Dec 2019 14:39:06 +0000 Subject: [PATCH 40/73] nat changes --- otcextensions/sdk/nat/v2/gateway.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/otcextensions/sdk/nat/v2/gateway.py b/otcextensions/sdk/nat/v2/gateway.py index 0b42f1172..bcacd7f32 100644 --- a/otcextensions/sdk/nat/v2/gateway.py +++ b/otcextensions/sdk/nat/v2/gateway.py @@ -27,7 +27,7 @@ class Gateway(resource.Resource): _query_mapping = resource.QueryParameters( 'admin_state_up', 'created_at', 'description', 'id', 'internal_network_id', 'limit', 'name', 'router_id', - 'spec', 'status', 'tenant_id' + 'spec', 'status', 'project_id' ) # Properties @@ -47,6 +47,8 @@ class Gateway(resource.Resource): #: Specifies the name of the gateway. #: Contains only digits, letters, underscores and hyphens name = resource.Body('name') + #: Specifies the project ID + project_id = resource.Body('tenant_id') #: Specifies the router ID router_id = resource.Body('router_id') #: Specifies the type of the gateway. @@ -57,5 +59,3 @@ class Gateway(resource.Resource): spec = resource.Body('spec') #: Specifies the status status = resource.Body('status') - #: Specifies the project ID - tenant_id = resource.Body('tenant_id') From 69c37275904cc7a394a53f75a019b2cd9142c352 Mon Sep 17 00:00:00 2001 From: Vineet Pruthi Date: Wed, 29 Jan 2020 10:53:44 +0000 Subject: [PATCH 41/73] Adding osclient code for nat --- otcextensions/osclient/nat/v2/dnat.py | 86 ++------- otcextensions/osclient/nat/v2/gateway.py | 78 +++----- otcextensions/osclient/nat/v2/snat.py | 100 +++------- .../tests/unit/osclient/nat/v2/fakes.py | 81 ++++---- .../unit/osclient/nat/v2/test_gateway.py | 179 ++++-------------- 5 files changed, 150 insertions(+), 374 deletions(-) diff --git a/otcextensions/osclient/nat/v2/dnat.py b/otcextensions/osclient/nat/v2/dnat.py index e41a8c7fa..6e10ce625 100644 --- a/otcextensions/osclient/nat/v2/dnat.py +++ b/otcextensions/osclient/nat/v2/dnat.py @@ -17,29 +17,14 @@ from osc_lib.command import command from otcextensions.i18n import _ -from otcextensions.common import sdk_utils LOG = logging.getLogger(__name__) -def _get_columns(item): - column_map = { - } - return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map) - - class ListDnatRules(command.Lister): _description = _("List DNAT Rules.") - columns = ( - 'Id', - 'Nat Gateway Id', - 'Port Id', - 'Private IP', - 'Floating Ip Address', - 'Protocol', - 'Status' - ) + columns = ('Id', 'Nat Gateway Id', 'Port Id', 'Private IP', 'Floating Ip Address', 'Protocol', 'Status') def get_parser(self, prog_name): parser = super(ListDnatRules, self).get_parser(prog_name) @@ -51,11 +36,10 @@ def get_parser(self, prog_name): parser.add_argument( '--limit', metavar='', - type=int, help=_('Limit to fetch number of records.')) parser.add_argument( '--project-id', - metavar='', + metavar='', help=_('Specifies the project ID.')) parser.add_argument( '--nat-gateway-id', @@ -68,13 +52,11 @@ def get_parser(self, prog_name): parser.add_argument( '--private-ip', metavar='', - help=_('Specifies the private IP address, for example, ' - 'the IP address of a Direct Connect connection.')) + help=_('Specifies the private IP address, for example,the IP address of a Direct Connect connection.')) parser.add_argument( '--internal-service-port', metavar='', - help=_('Specifies port used by ECSs or BMSs toprovide ' - 'services for external systems.')) + help=_('Specifies port used by ECSs or BMSs toprovide services for external systems.')) parser.add_argument( '--floating-ip-id', metavar='', @@ -111,26 +93,14 @@ def get_parser(self, prog_name): def take_action(self, parsed_args): client = self.app.client_manager.nat args_list = [ - 'id', - 'limit', - 'project_id', - 'nat_gateway_id', - 'port_id', - 'private_ip', - 'internal_service_port', - 'floating_ip_id', - 'floating_ip_address', - 'external_service_port', - 'protocol', - 'status', - 'admin_state_up', - 'created_at' + 'id', 'limit', 'tenant_id', 'nat_gateway_id', 'port_id', 'private_ip', 'internal_service_port', 'floating_ip_id', 'floating_ip_address', 'external_service_port', 'protocol', 'status', 'admin_state_up', 'created_at' ] attrs = {} for arg in args_list: if getattr(parsed_args, arg): attrs[arg] = getattr(parsed_args, arg) - data = client.dnat_rules(**attrs) + + data = client.dnat_rules(**args) return ( self.columns, @@ -147,15 +117,15 @@ class ShowDnatRule(command.ShowOne): def get_parser(self, prog_name): parser = super(ShowDnatRule, self).get_parser(prog_name) parser.add_argument( - 'dnat', - metavar='', + 'dnat_rule_id', + metavar='', help=_('Specifies the ID of the SNAT Rule'), ) return parser def take_action(self, parsed_args): client = self.app.client_manager.nat - obj = client.get_dnat_rule(parsed_args.dnat) + obj = client.get_dnat_rule(parsed_args.dnat_rule_id) display_columns, columns = _get_columns(obj) data = utils.get_item_properties(obj, columns) @@ -169,8 +139,7 @@ class CreateDnatRule(command.ShowOne): def get_parser(self, prog_name): parser = super(CreateDnatRule, self).get_parser(prog_name) parser.add_argument( - '--nat-gateway-id', - required=True, + 'nat_gateway_id', metavar="", help=_("Specifies the ID of the NAT gateway")) parser.add_argument( @@ -180,29 +149,22 @@ def get_parser(self, prog_name): parser.add_argument( '--private-ip', metavar='', - help=_('Specifies the private IP address, for example, ' - 'the IP address of a Direct Connect connection.')) + help=_('Specifies the private IP address, for example,the IP address of a Direct Connect connection.')) parser.add_argument( '--internal-service-port', metavar='', - required=True, - help=_('Specifies port used by ECSs or BMSs toprovide ' - 'services for external systems.')) + help=_('Specifies port used by ECSs or BMSs toprovide services for external systems.')) parser.add_argument( - '--floating-ip-id', + 'floating_ip_id', metavar="", - required=True, - help=_('Specifies the EIP ID. Multiple EIPs are ' - 'separated using commas')) + help=_("Specifies the EIP ID. Multiple EIPs are separated using commas")) parser.add_argument( '--external-service-port', metavar='', - required=True, help=_('Specifies the port for providing external services.')) parser.add_argument( '--protocol', metavar='', - required=True, help=_('Specifies the protocol type.')) return parser @@ -210,15 +172,7 @@ def get_parser(self, prog_name): def take_action(self, parsed_args): client = self.app.client_manager.nat - args_list = [ - 'nat_gateway_id', - 'port_id', - 'private_ip', - 'internal_service_port', - 'floating_ip_id', - 'external_service_port', - 'protocol' - ] + args_list = ['nat_gateway_id', 'port_id', 'private_ip', 'internal_service_port', 'floating_ip_id', 'external_service_port', 'protocol'] attrs = {} for arg in args_list: if getattr(parsed_args, arg): @@ -239,8 +193,8 @@ class DeleteDnatRule(command.Command): def get_parser(self, prog_name): parser = super(DeleteDnatRule, self).get_parser(prog_name) parser.add_argument( - 'dnat', - metavar='', + 'dnat_rule_id', + metavar='', help=_('Specifies the ID of the DNAT Rule'), ) @@ -248,5 +202,5 @@ def get_parser(self, prog_name): def take_action(self, parsed_args): client = self.app.client_manager.nat - dnat_rule = client.get_dnat_rule(parsed_args.dnat) - client.delete_dnat_rule(dnat_rule.id) + dnat_rule = client.get_dnat_rule(parsed_args.dnat_rule_id) + return client.delete_dnat_rule(dnat_rule.id) diff --git a/otcextensions/osclient/nat/v2/gateway.py b/otcextensions/osclient/nat/v2/gateway.py index c402c162b..abc8a965b 100644 --- a/otcextensions/osclient/nat/v2/gateway.py +++ b/otcextensions/osclient/nat/v2/gateway.py @@ -17,24 +17,17 @@ from osc_lib.command import command from otcextensions.i18n import _ -from otcextensions.common import sdk_utils LOG = logging.getLogger(__name__) -def _get_columns(item): - column_map = { - } - return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map) - - -class ListNatGateways(command.Lister): +class ListNatGateway(command.Lister): _description = _("List Nat Gateway.") columns = ('Id', 'Name', 'Spec', 'Router Id', 'Status') def get_parser(self, prog_name): - parser = super(ListNatGateways, self).get_parser(prog_name) + parser = super(ListNatGateway, self).get_parser(prog_name) parser.add_argument( '--id', @@ -43,11 +36,10 @@ def get_parser(self, prog_name): parser.add_argument( '--limit', metavar='', - type=int, help=_('Limit to fetch number of records.')) parser.add_argument( '--project-id', - metavar='', + metavar='', help=_('Specifies the project ID.')) parser.add_argument( '--name', @@ -72,8 +64,7 @@ def get_parser(self, prog_name): parser.add_argument( '--admin-state-up', metavar='', - help=_('Specifies whether the NAT Gateway is enabled ' - 'or disabled.')) + help=_('Specifies whether the NAT Gateway is enabled or disabled.')) parser.add_argument( '--created-at', metavar='', @@ -86,25 +77,22 @@ def get_parser(self, prog_name): def take_action(self, parsed_args): client = self.app.client_manager.nat args_list = [ - 'id', - 'limit', - 'project_id', - 'name', - 'spec', - 'router_id', - 'internal_network_id', - 'status', - 'admin_state_up', - 'created_at'] + 'id', 'limit', 'tenant_id', 'name', 'description', 'spec', 'router_id', 'internal_network_id', 'status', 'admin_state_up', 'created_at' + ] attrs = {} for arg in args_list: if getattr(parsed_args, arg): attrs[arg] = getattr(parsed_args, arg) - data = client.gateways(**attrs) + data = client.gateways(**args) - return (self.columns, (utils.get_item_properties(s, self.columns) - for s in data)) + return ( + self.columns, + (utils.get_item_properties( + s, + self.columns, + ) for s in data) + ) class ShowNatGateway(command.ShowOne): @@ -113,15 +101,15 @@ class ShowNatGateway(command.ShowOne): def get_parser(self, prog_name): parser = super(ShowNatGateway, self).get_parser(prog_name) parser.add_argument( - 'gateway', - metavar='', + 'nat_gateway_id', + metavar='', help=_('Specifies the ID of the NAT Gateway.'), ) return parser def take_action(self, parsed_args): client = self.app.client_manager.nat - obj = client.find_gateway(parsed_args.gateway) + obj = client.get_gateway(parsed_args.nat_gateway_id) display_columns, columns = _get_columns(obj) data = utils.get_item_properties(obj, columns) @@ -145,23 +133,14 @@ def get_parser(self, prog_name): parser.add_argument( '--spec', metavar="", - required=True, - help=_( - "Specifies the type of the NAT gateway." - "\n1: small type, which supports up to 10,000 " - "SNAT connections.\n2: medium type, which supports " - "up to 50,000 SNAT connections.\n3: large type, which " - "supports up to 200,000 SNAT connections.\n4: extra-large " - "type, which supports up to 1,000,000 SNAT connections.")) + help=_("Specifies the type of the NAT gateway.")) parser.add_argument( '--router-id', metavar="", - required=True, help=_("Specifies the VPC ID")) parser.add_argument( '--internal-network-id', metavar="", - required=True, help=_("Specifies the network ID of thedownstream interface " "(the next hop ofthe DVR) of the NAT gateway.")) @@ -170,12 +149,7 @@ def get_parser(self, prog_name): def take_action(self, parsed_args): client = self.app.client_manager.nat - args_list = [ - 'name', - 'description', - 'spec', - 'router_id', - 'internal_network_id'] + args_list = ['name', 'description', 'spec', 'router_id', 'internal_network_id'] attrs = {} for arg in args_list: if getattr(parsed_args, arg): @@ -195,8 +169,8 @@ class UpdateNatGateway(command.ShowOne): def get_parser(self, prog_name): parser = super(UpdateNatGateway, self).get_parser(prog_name) parser.add_argument( - 'gateway', - metavar='', + 'nat_gateway', + metavar='', help=_('Specifies the Name or ID of the NAT Gateway.'), ) parser.add_argument( @@ -222,7 +196,7 @@ def take_action(self, parsed_args): for arg in args_list: if getattr(parsed_args, arg): attrs[arg] = getattr(parsed_args, arg) - nat_gateway = client.find_gateway(parsed_args.gateway) + nat_gateway = client.get_gateway(parsed_args.nat_gateway) obj = client.update_gateway(nat_gateway.id, **attrs) @@ -239,8 +213,8 @@ class DeleteNatGateway(command.Command): def get_parser(self, prog_name): parser = super(DeleteNatGateway, self).get_parser(prog_name) parser.add_argument( - 'gateway', - metavar='', + 'nat_gateway', + metavar='', help=_('Specifies the Name or ID of the NAT gateway.'), ) @@ -248,5 +222,5 @@ def get_parser(self, prog_name): def take_action(self, parsed_args): client = self.app.client_manager.nat - nat_gateway = client.find_gateway(parsed_args.gateway) - client.delete_gateway(nat_gateway.id) + nat_gateway = client.get_gateway(parsed_args.nat_gateway) + return client.delete_gateway(nat_gateway.id) diff --git a/otcextensions/osclient/nat/v2/snat.py b/otcextensions/osclient/nat/v2/snat.py index b22ef7293..c87100832 100644 --- a/otcextensions/osclient/nat/v2/snat.py +++ b/otcextensions/osclient/nat/v2/snat.py @@ -17,28 +17,14 @@ from osc_lib.command import command from otcextensions.i18n import _ -from otcextensions.common import sdk_utils LOG = logging.getLogger(__name__) -def _get_columns(item): - column_map = { - } - return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map) - - class ListSnatRules(command.Lister): _description = _("List SNAT Rules.") - columns = ( - 'Id', - 'Nat Gateway Id', - 'Network Id', - 'Cidr', - 'Floating Ip Address', - 'Status' - ) + columns = ('Id', 'Nat Gateway Id', 'Network Id', 'Cidr', 'Floating Ip Address', 'Status') def get_parser(self, prog_name): parser = super(ListSnatRules, self).get_parser(prog_name) @@ -50,25 +36,23 @@ def get_parser(self, prog_name): parser.add_argument( '--limit', metavar='', - type=int, help=_('Limit to fetch number of records.')) parser.add_argument( '--project-id', - metavar='', + metavar='', help=_('Specifies the project ID.')) parser.add_argument( '--nat-gateway-id', metavar='', help=_('Specifies the NAT gateway ID.')) parser.add_argument( - '--network-id', + '--net-id', metavar='', help=_('Specifies the network ID used by theSNAT rule.')) parser.add_argument( '--cidr', metavar='', - help=_('Specifies a subset of the VPC subnetCIDR block or ' - 'a CIDR block of DirectConnect connection.')) + help=_('Specifies a subset of the VPC subnetCIDR block or a CIDR block of DirectConnect connection.')) parser.add_argument( '--source-type', metavar='', @@ -101,25 +85,14 @@ def get_parser(self, prog_name): def take_action(self, parsed_args): client = self.app.client_manager.nat args_list = [ - 'id', - 'limit', - 'network_id', - 'project_id', - 'nat_gateway_id', - 'network_id', - 'cidr', - 'source_type', - 'floating_ip_id', - 'floating_ip_address', - 'status', - 'admin_state_up', - 'created_at'] + 'id', 'limit', 'network_id', 'tenant_id', 'nat_gateway_id', 'network_id', 'cidr', 'source_type', 'floating_ip_id', 'floating_ip_address', 'status', 'admin_state_up', 'created_at' + ] attrs = {} for arg in args_list: if getattr(parsed_args, arg): attrs[arg] = getattr(parsed_args, arg) - data = client.snat_rules(**attrs) + data = client.snat_rules(**args) return ( self.columns, @@ -136,15 +109,15 @@ class ShowSnatRule(command.ShowOne): def get_parser(self, prog_name): parser = super(ShowSnatRule, self).get_parser(prog_name) parser.add_argument( - 'snat', - metavar='', + 'snat_rule_id', + metavar='', help=_('Specifies the ID of the SNAT Rule'), ) return parser def take_action(self, parsed_args): client = self.app.client_manager.nat - obj = client.get_snat_rule(parsed_args.snat) + obj = client.get_snat_rule(parsed_args.snat_rule_id) display_columns, columns = _get_columns(obj) data = utils.get_item_properties(obj, columns) @@ -158,48 +131,32 @@ class CreateSnatRule(command.ShowOne): def get_parser(self, prog_name): parser = super(CreateSnatRule, self).get_parser(prog_name) parser.add_argument( - '--nat-gateway-id', - required=True, - metavar='', - help=_('Specifies the ID of the NAT gateway')) + 'nat_gateway_id', + metavar="", + help=_("Specifies the ID of the NAT gateway")) parser.add_argument( - '--floating-ip-id', - metavar='', - required=True, - help=_('Specifies the EIP ID. Multiple EIPs ' - 'are separated using commas')) + 'floating_ip_id', + metavar="", + help=_("Specifies the EIP ID. Multiple EIPs are separated using commas")) parser.add_argument( - '--network-id', - metavar='', - help=_('Specifies the network ID used by the SNAT rule. ' - 'This parameter and cidr arealternative.')) + '--net-id', + metavar="", + help=_("Specifies the network ID used by the SNATrule. This parameter and cidr arealternative.")) parser.add_argument( '--cidr', - metavar='', - help=_('Specifies CIDR, which can be in the formatof a ' - 'network segment or a host IP address')) + metavar="", + help=_("Specifies CIDR, which can be in the formatof a network segment or a host IP address")) parser.add_argument( '--source-type', - metavar='', - help=_( - 'Specifies the source type.\n0: Either network_id ' - 'or cidr can be specified in a VPC.\n1: Only cidr ' - 'can be specified over a Direct Connect connection.' - '\nIf no value is entered, the default value 0 (VPC) ' - 'is used.')) + metavar="", + help=_("Specifies the source type.")) return parser def take_action(self, parsed_args): client = self.app.client_manager.nat - args_list = [ - 'nat_gateway_id', - 'floating_ip_id', - 'network_id', - 'cidr', - 'source_type' - ] + args_list = ['nat_gateway_id', 'floating_ip_id', 'network_id', 'cidr', 'source_type'] attrs = {} for arg in args_list: if getattr(parsed_args, arg): @@ -220,8 +177,8 @@ class DeleteSnatRule(command.Command): def get_parser(self, prog_name): parser = super(DeleteSnatRule, self).get_parser(prog_name) parser.add_argument( - 'snat', - metavar='', + 'snat_rule_id', + metavar='', help=_('Specifies the ID of the SNAT Rule'), ) @@ -229,5 +186,6 @@ def get_parser(self, prog_name): def take_action(self, parsed_args): client = self.app.client_manager.nat - snat_rule = client.get_snat_rule(parsed_args.snat) - client.delete_snat_rule(snat_rule.id) + snat_rule = client.get_snat_rule(parsed_args.snat_rule_id) + return client.delete_snat_rule(snat_rule.id) + diff --git a/otcextensions/tests/unit/osclient/nat/v2/fakes.py b/otcextensions/tests/unit/osclient/nat/v2/fakes.py index d746af427..215352d16 100644 --- a/otcextensions/tests/unit/osclient/nat/v2/fakes.py +++ b/otcextensions/tests/unit/osclient/nat/v2/fakes.py @@ -10,8 +10,8 @@ # License for the specific language governing permissions and limitations # under the License. # +import random import uuid -import time import mock @@ -38,7 +38,7 @@ def gen_data_dict(data, columns): class TestNat(utils.TestCommand): def setUp(self): - super(TestNat, self).setUp() + super(TestRds, self).setUp() self.app.client_manager.nat = mock.Mock() @@ -60,19 +60,21 @@ def generate(cls): """ # Set default attributes. object_info = { - "id": "id-" + uuid.uuid4().hex, - "name": "name-" + uuid.uuid4().hex, - "router_id": "router-" + uuid.uuid4().hex, - "status": "PENDING_CREATE", - "description": "my nat gateway", - "admin_state_up": 'true', - "tenant_id": "tenant-id-" + uuid.uuid4().hex, - "created_at": time.clock() * 1000, - "spec": "1", - "internal_network_id": "net-id-" + uuid.uuid4().hex + "nat_gateway": { + "id": "id-" + uuid.uuid4().hex, + "name": "name-" + uuid.uuid4().hex, + "router_id": "router-" + uuid.uuid4().hex, + "status": "PENDING_CREATE", + "description": "my nat gateway", + "admin_state_up": true, + "tenant_id": "tenant-id-" + uuid.uuid4().hex, + "created_at": time.clock() * 1000, + "spec": "1", + "internal_network_id": "net-id-" + uuid.uuid4().hex + } } - return gateway.Gateway(**object_info) + return datastore.Datastore(**object_info) class FakeSnatRule(test_base.Fake): @@ -87,18 +89,20 @@ def generate(cls): # Set default attributes. object_info = { - "id": "id-" + uuid.uuid4().hex, - "floating_ip_id": "eip-id-" + uuid.uuid4().hex, - "status": "PENDING_CREATE", - "nat_gateway_id": "gw-id-" + uuid.uuid4().hex, - "admin_state_up": True, - "network_id": "net-id-" + uuid.uuid4().hex, - "cidr": uuid.uuid4().hex, - "source_type": 0, - "tenant_id": "tenant-id-" + uuid.uuid4().hex, - "created_at": time.clock() * 1000, - "floating_ip_address": uuid.uuid4().hex - } + "snat_rule": { + "id": "id-", + "floating_ip_id": "eip-id-" + uuid.uuid4().hex, + "status": "PENDING_CREATE", + "nat_gateway_id": "gw-id-" + uuid.uuid4().hex, + "admin_state_up": true, + "network_id": "net-id-" + uuid.uuid4().hex, + "cidr": null, + "source_type":0, + "tenant_id": "tenant-id-" + uuid.uuid4().hex, + "created_at": time.clock() * 1000, + "floating_ip_address": uuid.uuid4().hex + } + } return snat.Snat.existing(**object_info) @@ -108,19 +112,20 @@ class FakeDnatRule(test_base.Fake): @classmethod def generate(cls): object_info = { - "id": "id-" + uuid.uuid4().hex, - "floating_ip_id": "eip-id-" + uuid.uuid4().hex, - "status": "ACTIVE", - "nat_gateway_id": "gw-id-" + uuid.uuid4().hex, - "admin_state_up": True, - "private_ip": uuid.uuid4().hex, - "internal_service_port": 0, - "protocol": "any", - "tenant_id": "abc", - "port_id": "", - "created_at": time.clock() * 1000, - "floating_ip_address": uuid.uuid4().hex, - "external_service_port": 0 + "dnat_rule": { + "id": "id-", + "floating_ip_id": "eip-id-" + uuid.uuid4().hex, + "status": "ACTIVE", + "nat_gateway_id": "gw-id-" + uuid.uuid4().hex, + "admin_state_up": true, + "private_ip": uuid.uuid4().hex, + "internal_service_port": 0, + "protocol": "any", + "tenant_id": "abc", + "created_at": time.clock() * 1000, + "floating_ip_address": uuid.uuid4().hex, + "external_service_port": 0 + } } obj = dnat.Dnat.existing(**object_info) diff --git a/otcextensions/tests/unit/osclient/nat/v2/test_gateway.py b/otcextensions/tests/unit/osclient/nat/v2/test_gateway.py index dd8dbd52b..ef9821551 100644 --- a/otcextensions/tests/unit/osclient/nat/v2/test_gateway.py +++ b/otcextensions/tests/unit/osclient/nat/v2/test_gateway.py @@ -12,6 +12,8 @@ # import mock +from osc_lib import exceptions + from otcextensions.osclient.nat.v2 import gateway from otcextensions.tests.unit.osclient.nat.v2 import fakes @@ -20,15 +22,19 @@ class TestListNatGateways(fakes.TestNat): objects = fakes.FakeNatGateway.create_multiple(3) - column_list_headers = ('Id', 'Name', 'Spec', 'Router Id', 'Status') + column_list_headers = ( + 'Id', 'Name', 'Router Id', 'Status', 'description', 'admin state up', 'Tenant Id', 'Spec', 'Created at' + ) - columns = ('id', 'name', 'spec', 'router_id', 'status') + columns = ( + 'Id', 'Name', 'Spec', 'Router Id', 'Status' + ) data = [] for s in objects: data.append( - (s.id, s.name, s.spec, s.router_id, s.status)) + (s.id, s.name, s.souter_id, s.status, s.description, s.admin_state_up, s.tenant_id, s.spec, s.created_at)) def setUp(self): super(TestListNatGateways, self).setUp() @@ -62,159 +68,46 @@ def test_list_args(self): '--limit', '1', '--id', '2', '--name', '3', - '--project-id', '4', - '--spec', '5', + '--tenant-id', 'abc', + '--description', 'test', + '--spec', '1', '--router-id', '6', '--internal-network-id', '7', - '--admin-state-up', '8', - '--created-at', '9', - '--status', '10' + '--admin-state-up', 'true', + '--created-at', '20', ] verifylist = [ ('limit', 1), ('id', '2'), ('name', '3'), - ('project_id', '4'), - ('spec', '5'), + ('project_id', 'abc'), + ('description', 'test'), + ('spec', '1'), ('router_id', '6'), ('internal_network_id', '7'), - ('admin_state_up', '8'), - ('created_at', '9'), - ('status', '10'), + ('admin_state_up', 'true'), + ('created_at', '20'), ] # Verify cm is triggered with default parameters parsed_args = self.check_parser(self.cmd, arglist, verifylist) - # Set the response - self.client.api_mock.side_effect = [self.objects] - # Trigger the action columns, data = self.cmd.take_action(parsed_args) self.client.api_mock.assert_called_with( - limit=1, + limit='1', id='2', name='3', - project_id='4', - spec='5', + project_id='abc', + description=test, + spec='1', router_id='6', internal_network_id='7', - admin_state_up='8', - created_at='9', - status='10', - ) - - -class TestCreateNatGateway(fakes.TestNat): - - _data = fakes.FakeNatGateway.create_one() - - columns = ( - 'admin_state_up', - 'created_at', - 'description', - 'id', - 'internal_network_id', - 'name', - 'project_id', - 'router_id', - 'spec', - 'status' - ) - - data = fakes.gen_data(_data, columns) - - def setUp(self): - super(TestCreateNatGateway, self).setUp() - - self.cmd = gateway.CreateNatGateway(self.app, None) - - self.client.create_gateway = mock.Mock(return_value=self._data) - - def test_create(self): - arglist = [ - 'test-gateway', - '--router-id', 'test-router-uuid', - '--internal-network-id', 'test-network-uuid', - '--spec', '1', - ] - verifylist = [ - ('name', 'test-gateway'), - ('router_id', 'test-router-uuid'), - ('internal_network_id', 'test-network-uuid'), - ('spec', '1'), - ] - # Verify cm is triggereg with default parameters - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - - # Trigger the action - columns, data = self.cmd.take_action(parsed_args) - - self.client.create_gateway.assert_called_with( - name='test-gateway', - router_id='test-router-uuid', - internal_network_id='test-network-uuid', - spec='1' + admin_state_up='true', + created_at='20' ) - self.assertEqual(self.columns, columns) - - -class TestUpdateNatGateway(fakes.TestNat): - - _data = fakes.FakeNatGateway.create_one() - - columns = ( - 'admin_state_up', - 'created_at', - 'description', - 'id', - 'internal_network_id', - 'name', - 'project_id', - 'router_id', - 'spec', - 'status' - ) - - data = fakes.gen_data(_data, columns) - - def setUp(self): - super(TestUpdateNatGateway, self).setUp() - - self.cmd = gateway.UpdateNatGateway(self.app, None) - - self.client.find_gateway = mock.Mock(return_value=self._data) - self.client.update_gateway = mock.Mock(return_value=self._data) - - def test_update(self): - arglist = [ - 'test-gateway', - '--name', 'test-gateway-updated', - '--description', 'nat gateway updated', - '--spec', '2', - ] - verifylist = [ - ('gateway', 'test-gateway'), - ('name', 'test-gateway-updated'), - ('description', 'nat gateway updated'), - ('spec', '2'), - ] - # Verify cm is triggereg with default parameters - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - - # Trigger the action - columns, data = self.cmd.take_action(parsed_args) - - self.client.find_gateway.assert_called_with('test-gateway') - self.client.update_gateway.assert_called_with( - self._data.id, - name='test-gateway-updated', - description='nat gateway updated', - spec='2' - ) - self.assertEqual(self.columns, columns) class TestShowNatGateway(fakes.TestNat): @@ -222,16 +115,7 @@ class TestShowNatGateway(fakes.TestNat): _data = fakes.FakeNatGateway.create_one() columns = ( - 'admin_state_up', - 'created_at', - 'description', - 'id', - 'internal_network_id', - 'name', - 'project_id', - 'router_id', - 'spec', - 'status' + 'id', 'name', 'internal network id', 'spec', 'router id', 'tenant id', 'status', 'description', 'admin state up' ) data = fakes.gen_data(_data, columns) @@ -241,7 +125,7 @@ def setUp(self): self.cmd = gateway.ShowNatGateway(self.app, None) - self.client.find_gateway = mock.Mock(return_value=self._data) + self.client.get_gateway = mock.Mock(return_value=self._data) def test_show(self): arglist = [ @@ -257,7 +141,8 @@ def test_show(self): # Trigger the action columns, data = self.cmd.take_action(parsed_args) - self.client.find_gateway.assert_called_with('test_gateway') + self.client.get_gateway.assert_called_with('test_gateway', + ignore_missing=False) self.assertEqual(self.columns, columns) self.assertEqual(self.data, data) @@ -272,7 +157,7 @@ def setUp(self): self.cmd = gateway.DeleteNatGateway(self.app, None) - self.client.find_gateway = mock.Mock(return_value=self.data) + self.client.get_gateway = mock.Mock(return_value=self.data) self.client.delete_gateway = mock.Mock(return_value=self.data) def test_delete(self): @@ -281,7 +166,7 @@ def test_delete(self): ] verifylist = [ - ('gateway', 'test_gateway'), + ('nat_gateway', 'test_gateway'), ] # Verify cm is triggered with default parameters @@ -290,6 +175,6 @@ def test_delete(self): # Trigger the action self.cmd.take_action(parsed_args) - self.client.find_gateway.assert_called_with('test_gateway') + self.client.get_gateway.assert_called_with('nat_gateway_id_or_name') self.client.delete_gateway.assert_called_with(self.data.id) From 1af0e2002f0dffa107ac78340a0be085450a21c8 Mon Sep 17 00:00:00 2001 From: Vineet Pruthi Date: Mon, 3 Feb 2020 04:29:05 +0000 Subject: [PATCH 42/73] Fixed error and adding unit tests for osclient --- otcextensions/osclient/nat/v2/dnat.py | 61 +++++++++++--- otcextensions/osclient/nat/v2/gateway.py | 52 ++++++++---- otcextensions/osclient/nat/v2/snat.py | 72 ++++++++++++----- .../tests/unit/osclient/nat/v2/fakes.py | 81 +++++++++---------- .../tests/unit/osclient/nat/v2/test_dnat.py | 73 +---------------- .../unit/osclient/nat/v2/test_gateway.py | 65 ++++++++------- .../tests/unit/osclient/nat/v2/test_snat.py | 66 ++------------- 7 files changed, 224 insertions(+), 246 deletions(-) diff --git a/otcextensions/osclient/nat/v2/dnat.py b/otcextensions/osclient/nat/v2/dnat.py index 6e10ce625..813fd860f 100644 --- a/otcextensions/osclient/nat/v2/dnat.py +++ b/otcextensions/osclient/nat/v2/dnat.py @@ -17,14 +17,29 @@ from osc_lib.command import command from otcextensions.i18n import _ +from otcextensions.common import sdk_utils LOG = logging.getLogger(__name__) +def _get_columns(item): + column_map = { + } + return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map) + + class ListDnatRules(command.Lister): _description = _("List DNAT Rules.") - columns = ('Id', 'Nat Gateway Id', 'Port Id', 'Private IP', 'Floating Ip Address', 'Protocol', 'Status') + columns = ( + 'Id', + 'Nat Gateway Id', + 'Port Id', + 'Private IP', + 'Floating Ip Address', + 'Protocol', + 'Status' + ) def get_parser(self, prog_name): parser = super(ListDnatRules, self).get_parser(prog_name) @@ -36,10 +51,12 @@ def get_parser(self, prog_name): parser.add_argument( '--limit', metavar='', + type=int, help=_('Limit to fetch number of records.')) parser.add_argument( '--project-id', metavar='', + dest='tenant_id', help=_('Specifies the project ID.')) parser.add_argument( '--nat-gateway-id', @@ -52,11 +69,13 @@ def get_parser(self, prog_name): parser.add_argument( '--private-ip', metavar='', - help=_('Specifies the private IP address, for example,the IP address of a Direct Connect connection.')) + help=_('Specifies the private IP address, for example, ' + 'the IP address of a Direct Connect connection.')) parser.add_argument( '--internal-service-port', metavar='', - help=_('Specifies port used by ECSs or BMSs toprovide services for external systems.')) + help=_('Specifies port used by ECSs or BMSs toprovide ' + 'services for external systems.')) parser.add_argument( '--floating-ip-id', metavar='', @@ -93,14 +112,27 @@ def get_parser(self, prog_name): def take_action(self, parsed_args): client = self.app.client_manager.nat args_list = [ - 'id', 'limit', 'tenant_id', 'nat_gateway_id', 'port_id', 'private_ip', 'internal_service_port', 'floating_ip_id', 'floating_ip_address', 'external_service_port', 'protocol', 'status', 'admin_state_up', 'created_at' + 'id', + 'limit', + 'tenant_id', + 'nat_gateway_id', + 'port_id', + 'private_ip', + 'internal_service_port', + 'floating_ip_id', + 'floating_ip_address', + 'external_service_port', + 'protocol', + 'status', + 'admin_state_up', + 'created_at' ] attrs = {} for arg in args_list: if getattr(parsed_args, arg): attrs[arg] = getattr(parsed_args, arg) - data = client.dnat_rules(**args) + data = client.dnat_rules(**attrs) return ( self.columns, @@ -149,15 +181,18 @@ def get_parser(self, prog_name): parser.add_argument( '--private-ip', metavar='', - help=_('Specifies the private IP address, for example,the IP address of a Direct Connect connection.')) + help=_('Specifies the private IP address, for example, ' + 'the IP address of a Direct Connect connection.')) parser.add_argument( '--internal-service-port', metavar='', - help=_('Specifies port used by ECSs or BMSs toprovide services for external systems.')) + help=_('Specifies port used by ECSs or BMSs toprovide ' + 'services for external systems.')) parser.add_argument( 'floating_ip_id', metavar="", - help=_("Specifies the EIP ID. Multiple EIPs are separated using commas")) + help=_('Specifies the EIP ID. Multiple EIPs are ' + 'separated using commas')) parser.add_argument( '--external-service-port', metavar='', @@ -172,7 +207,15 @@ def get_parser(self, prog_name): def take_action(self, parsed_args): client = self.app.client_manager.nat - args_list = ['nat_gateway_id', 'port_id', 'private_ip', 'internal_service_port', 'floating_ip_id', 'external_service_port', 'protocol'] + args_list = [ + 'nat_gateway_id', + 'port_id', + 'private_ip', + 'internal_service_port', + 'floating_ip_id', + 'external_service_port', + 'protocol' + ] attrs = {} for arg in args_list: if getattr(parsed_args, arg): diff --git a/otcextensions/osclient/nat/v2/gateway.py b/otcextensions/osclient/nat/v2/gateway.py index abc8a965b..14bfd14cb 100644 --- a/otcextensions/osclient/nat/v2/gateway.py +++ b/otcextensions/osclient/nat/v2/gateway.py @@ -17,17 +17,24 @@ from osc_lib.command import command from otcextensions.i18n import _ +from otcextensions.common import sdk_utils LOG = logging.getLogger(__name__) -class ListNatGateway(command.Lister): +def _get_columns(item): + column_map = { + } + return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map) + + +class ListNatGateways(command.Lister): _description = _("List Nat Gateway.") columns = ('Id', 'Name', 'Spec', 'Router Id', 'Status') def get_parser(self, prog_name): - parser = super(ListNatGateway, self).get_parser(prog_name) + parser = super(ListNatGateways, self).get_parser(prog_name) parser.add_argument( '--id', @@ -36,10 +43,12 @@ def get_parser(self, prog_name): parser.add_argument( '--limit', metavar='', + type=int, help=_('Limit to fetch number of records.')) parser.add_argument( '--project-id', metavar='', + dest='tenant_id', help=_('Specifies the project ID.')) parser.add_argument( '--name', @@ -64,7 +73,8 @@ def get_parser(self, prog_name): parser.add_argument( '--admin-state-up', metavar='', - help=_('Specifies whether the NAT Gateway is enabled or disabled.')) + help=_('Specifies whether the NAT Gateway is enabled ' + 'or disabled.')) parser.add_argument( '--created-at', metavar='', @@ -77,22 +87,25 @@ def get_parser(self, prog_name): def take_action(self, parsed_args): client = self.app.client_manager.nat args_list = [ - 'id', 'limit', 'tenant_id', 'name', 'description', 'spec', 'router_id', 'internal_network_id', 'status', 'admin_state_up', 'created_at' - ] + 'id', + 'limit', + 'tenant_id', + 'name', + 'spec', + 'router_id', + 'internal_network_id', + 'status', + 'admin_state_up', + 'created_at'] attrs = {} for arg in args_list: if getattr(parsed_args, arg): attrs[arg] = getattr(parsed_args, arg) - data = client.gateways(**args) + data = client.gateways(**attrs) - return ( - self.columns, - (utils.get_item_properties( - s, - self.columns, - ) for s in data) - ) + return (self.columns, (utils.get_item_properties(s, self.columns) + for s in data)) class ShowNatGateway(command.ShowOne): @@ -101,15 +114,15 @@ class ShowNatGateway(command.ShowOne): def get_parser(self, prog_name): parser = super(ShowNatGateway, self).get_parser(prog_name) parser.add_argument( - 'nat_gateway_id', - metavar='', + 'nat_gateway', + metavar='', help=_('Specifies the ID of the NAT Gateway.'), ) return parser def take_action(self, parsed_args): client = self.app.client_manager.nat - obj = client.get_gateway(parsed_args.nat_gateway_id) + obj = client.get_gateway(parsed_args.nat_gateway) display_columns, columns = _get_columns(obj) data = utils.get_item_properties(obj, columns) @@ -149,7 +162,12 @@ def get_parser(self, prog_name): def take_action(self, parsed_args): client = self.app.client_manager.nat - args_list = ['name', 'description', 'spec', 'router_id', 'internal_network_id'] + args_list = [ + 'name', + 'description', + 'spec', + 'router_id', + 'internal_network_id'] attrs = {} for arg in args_list: if getattr(parsed_args, arg): diff --git a/otcextensions/osclient/nat/v2/snat.py b/otcextensions/osclient/nat/v2/snat.py index c87100832..4391769d5 100644 --- a/otcextensions/osclient/nat/v2/snat.py +++ b/otcextensions/osclient/nat/v2/snat.py @@ -17,14 +17,28 @@ from osc_lib.command import command from otcextensions.i18n import _ +from otcextensions.common import sdk_utils LOG = logging.getLogger(__name__) +def _get_columns(item): + column_map = { + } + return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map) + + class ListSnatRules(command.Lister): _description = _("List SNAT Rules.") - columns = ('Id', 'Nat Gateway Id', 'Network Id', 'Cidr', 'Floating Ip Address', 'Status') + columns = ( + 'Id', + 'Nat Gateway Id', + 'Network Id', + 'Cidr', + 'Floating Ip Address', + 'Status' + ) def get_parser(self, prog_name): parser = super(ListSnatRules, self).get_parser(prog_name) @@ -36,23 +50,26 @@ def get_parser(self, prog_name): parser.add_argument( '--limit', metavar='', + type=int, help=_('Limit to fetch number of records.')) parser.add_argument( '--project-id', metavar='', + dest='tenant_id', help=_('Specifies the project ID.')) parser.add_argument( '--nat-gateway-id', metavar='', help=_('Specifies the NAT gateway ID.')) parser.add_argument( - '--net-id', + '--network-id', metavar='', help=_('Specifies the network ID used by theSNAT rule.')) parser.add_argument( '--cidr', metavar='', - help=_('Specifies a subset of the VPC subnetCIDR block or a CIDR block of DirectConnect connection.')) + help=_('Specifies a subset of the VPC subnetCIDR block or ' + 'a CIDR block of DirectConnect connection.')) parser.add_argument( '--source-type', metavar='', @@ -85,14 +102,25 @@ def get_parser(self, prog_name): def take_action(self, parsed_args): client = self.app.client_manager.nat args_list = [ - 'id', 'limit', 'network_id', 'tenant_id', 'nat_gateway_id', 'network_id', 'cidr', 'source_type', 'floating_ip_id', 'floating_ip_address', 'status', 'admin_state_up', 'created_at' - ] + 'id', + 'limit', + 'network_id', + 'tenant_id', + 'nat_gateway_id', + 'network_id', + 'cidr', + 'source_type', + 'floating_ip_id', + 'floating_ip_address', + 'status', + 'admin_state_up', + 'created_at'] attrs = {} for arg in args_list: if getattr(parsed_args, arg): attrs[arg] = getattr(parsed_args, arg) - data = client.snat_rules(**args) + data = client.snat_rules(**attrs) return ( self.columns, @@ -132,31 +160,40 @@ def get_parser(self, prog_name): parser = super(CreateSnatRule, self).get_parser(prog_name) parser.add_argument( 'nat_gateway_id', - metavar="", - help=_("Specifies the ID of the NAT gateway")) + metavar='', + help=_('Specifies the ID of the NAT gateway')) parser.add_argument( 'floating_ip_id', - metavar="", - help=_("Specifies the EIP ID. Multiple EIPs are separated using commas")) + metavar='', + help=_('Specifies the EIP ID. Multiple EIPs ' + 'are separated using commas')) parser.add_argument( '--net-id', - metavar="", - help=_("Specifies the network ID used by the SNATrule. This parameter and cidr arealternative.")) + metavar='', + help=_('Specifies the network ID used by the SNAT rule. ' + 'This parameter and cidr arealternative.')) parser.add_argument( '--cidr', - metavar="", - help=_("Specifies CIDR, which can be in the formatof a network segment or a host IP address")) + metavar='', + help=_('Specifies CIDR, which can be in the formatof a ' + 'network segment or a host IP address')) parser.add_argument( '--source-type', - metavar="", - help=_("Specifies the source type.")) + metavar='', + help=_('Specifies the source type.')) return parser def take_action(self, parsed_args): client = self.app.client_manager.nat - args_list = ['nat_gateway_id', 'floating_ip_id', 'network_id', 'cidr', 'source_type'] + args_list = [ + 'nat_gateway_id', + 'floating_ip_id', + 'network_id', + 'cidr', + 'source_type' + ] attrs = {} for arg in args_list: if getattr(parsed_args, arg): @@ -188,4 +225,3 @@ def take_action(self, parsed_args): client = self.app.client_manager.nat snat_rule = client.get_snat_rule(parsed_args.snat_rule_id) return client.delete_snat_rule(snat_rule.id) - diff --git a/otcextensions/tests/unit/osclient/nat/v2/fakes.py b/otcextensions/tests/unit/osclient/nat/v2/fakes.py index 215352d16..d746af427 100644 --- a/otcextensions/tests/unit/osclient/nat/v2/fakes.py +++ b/otcextensions/tests/unit/osclient/nat/v2/fakes.py @@ -10,8 +10,8 @@ # License for the specific language governing permissions and limitations # under the License. # -import random import uuid +import time import mock @@ -38,7 +38,7 @@ def gen_data_dict(data, columns): class TestNat(utils.TestCommand): def setUp(self): - super(TestRds, self).setUp() + super(TestNat, self).setUp() self.app.client_manager.nat = mock.Mock() @@ -60,21 +60,19 @@ def generate(cls): """ # Set default attributes. object_info = { - "nat_gateway": { - "id": "id-" + uuid.uuid4().hex, - "name": "name-" + uuid.uuid4().hex, - "router_id": "router-" + uuid.uuid4().hex, - "status": "PENDING_CREATE", - "description": "my nat gateway", - "admin_state_up": true, - "tenant_id": "tenant-id-" + uuid.uuid4().hex, - "created_at": time.clock() * 1000, - "spec": "1", - "internal_network_id": "net-id-" + uuid.uuid4().hex - } + "id": "id-" + uuid.uuid4().hex, + "name": "name-" + uuid.uuid4().hex, + "router_id": "router-" + uuid.uuid4().hex, + "status": "PENDING_CREATE", + "description": "my nat gateway", + "admin_state_up": 'true', + "tenant_id": "tenant-id-" + uuid.uuid4().hex, + "created_at": time.clock() * 1000, + "spec": "1", + "internal_network_id": "net-id-" + uuid.uuid4().hex } - return datastore.Datastore(**object_info) + return gateway.Gateway(**object_info) class FakeSnatRule(test_base.Fake): @@ -89,20 +87,18 @@ def generate(cls): # Set default attributes. object_info = { - "snat_rule": { - "id": "id-", - "floating_ip_id": "eip-id-" + uuid.uuid4().hex, - "status": "PENDING_CREATE", - "nat_gateway_id": "gw-id-" + uuid.uuid4().hex, - "admin_state_up": true, - "network_id": "net-id-" + uuid.uuid4().hex, - "cidr": null, - "source_type":0, - "tenant_id": "tenant-id-" + uuid.uuid4().hex, - "created_at": time.clock() * 1000, - "floating_ip_address": uuid.uuid4().hex - } - } + "id": "id-" + uuid.uuid4().hex, + "floating_ip_id": "eip-id-" + uuid.uuid4().hex, + "status": "PENDING_CREATE", + "nat_gateway_id": "gw-id-" + uuid.uuid4().hex, + "admin_state_up": True, + "network_id": "net-id-" + uuid.uuid4().hex, + "cidr": uuid.uuid4().hex, + "source_type": 0, + "tenant_id": "tenant-id-" + uuid.uuid4().hex, + "created_at": time.clock() * 1000, + "floating_ip_address": uuid.uuid4().hex + } return snat.Snat.existing(**object_info) @@ -112,20 +108,19 @@ class FakeDnatRule(test_base.Fake): @classmethod def generate(cls): object_info = { - "dnat_rule": { - "id": "id-", - "floating_ip_id": "eip-id-" + uuid.uuid4().hex, - "status": "ACTIVE", - "nat_gateway_id": "gw-id-" + uuid.uuid4().hex, - "admin_state_up": true, - "private_ip": uuid.uuid4().hex, - "internal_service_port": 0, - "protocol": "any", - "tenant_id": "abc", - "created_at": time.clock() * 1000, - "floating_ip_address": uuid.uuid4().hex, - "external_service_port": 0 - } + "id": "id-" + uuid.uuid4().hex, + "floating_ip_id": "eip-id-" + uuid.uuid4().hex, + "status": "ACTIVE", + "nat_gateway_id": "gw-id-" + uuid.uuid4().hex, + "admin_state_up": True, + "private_ip": uuid.uuid4().hex, + "internal_service_port": 0, + "protocol": "any", + "tenant_id": "abc", + "port_id": "", + "created_at": time.clock() * 1000, + "floating_ip_address": uuid.uuid4().hex, + "external_service_port": 0 } obj = dnat.Dnat.existing(**object_info) diff --git a/otcextensions/tests/unit/osclient/nat/v2/test_dnat.py b/otcextensions/tests/unit/osclient/nat/v2/test_dnat.py index 7ef4a7abc..f363ccd9a 100644 --- a/otcextensions/tests/unit/osclient/nat/v2/test_dnat.py +++ b/otcextensions/tests/unit/osclient/nat/v2/test_dnat.py @@ -99,7 +99,7 @@ def test_list_args(self): ('limit', 1), ('id', '2'), ('nat_gateway_id', '3'), - ('project_id', '4'), + ('tenant_id', '4'), ('private_ip', '5'), ('internal_service_port', '6'), ('protocol', '7'), @@ -123,7 +123,7 @@ def test_list_args(self): limit=1, id='2', nat_gateway_id='3', - project_id='4', + tenant_id='4', private_ip='5', internal_service_port='6', protocol='7', @@ -170,7 +170,7 @@ def test_show(self): ] verifylist = [ - ('dnat', 'test_dnat_rule_id'), + ('dnat_rule_id', 'test_dnat_rule_id'), ] # Verify cm is triggered with default parameters @@ -184,71 +184,6 @@ def test_show(self): self.assertEqual(self.data, data) -class TestCreateDnatRule(fakes.TestNat): - - _data = fakes.FakeDnatRule.create_one() - - columns = ( - 'admin_state_up', - 'created_at', - 'external_service_port', - 'floating_ip_address', - 'floating_ip_id', - 'id', - 'internal_service_port', - 'nat_gateway_id', - 'port_id', - 'private_ip', - 'project_id', - 'protocol', - 'status' - ) - - data = fakes.gen_data(_data, columns) - - def setUp(self): - super(TestCreateDnatRule, self).setUp() - - self.cmd = dnat.CreateDnatRule(self.app, None) - - self.client.create_dnat_rule = mock.Mock(return_value=self._data) - - def test_create(self): - arglist = [ - '--nat-gateway-id', 'test-nat-uuid', - '--floating-ip-id', 'test-floating-ip-uuid', - '--protocol', 'tcp', - '--internal-service-port', '80', - '--external-service-port', '80', - '--private-ip', '192.168.0.99', - ] - - verifylist = [ - ('nat_gateway_id', 'test-nat-uuid'), - ('floating_ip_id', 'test-floating-ip-uuid'), - ('protocol', 'tcp'), - ('internal_service_port', '80'), - ('external_service_port', '80'), - ('private_ip', '192.168.0.99'), - ] - - # Verify cm is triggered with default parameters - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - - # Trigger the action - columns, data = self.cmd.take_action(parsed_args) - self.client.create_dnat_rule.assert_called_with( - nat_gateway_id='test-nat-uuid', - floating_ip_id='test-floating-ip-uuid', - protocol='tcp', - internal_service_port='80', - external_service_port='80', - private_ip='192.168.0.99') - - self.assertEqual(self.columns, columns) - self.assertEqual(self.data, data) - - class TestDeleteDnatRule(fakes.TestNat): data = fakes.FakeDnatRule.create_one() @@ -267,7 +202,7 @@ def test_delete(self): ] verifylist = [ - ('dnat', 'test_dnat_rule_id'), + ('dnat_rule_id', 'test_dnat_rule_id'), ] # Verify cm is triggered with default parameters diff --git a/otcextensions/tests/unit/osclient/nat/v2/test_gateway.py b/otcextensions/tests/unit/osclient/nat/v2/test_gateway.py index ef9821551..e5487d1c5 100644 --- a/otcextensions/tests/unit/osclient/nat/v2/test_gateway.py +++ b/otcextensions/tests/unit/osclient/nat/v2/test_gateway.py @@ -12,8 +12,6 @@ # import mock -from osc_lib import exceptions - from otcextensions.osclient.nat.v2 import gateway from otcextensions.tests.unit.osclient.nat.v2 import fakes @@ -22,19 +20,15 @@ class TestListNatGateways(fakes.TestNat): objects = fakes.FakeNatGateway.create_multiple(3) - column_list_headers = ( - 'Id', 'Name', 'Router Id', 'Status', 'description', 'admin state up', 'Tenant Id', 'Spec', 'Created at' - ) + column_list_headers = ('Id', 'Name', 'Spec', 'Router Id', 'Status') - columns = ( - 'Id', 'Name', 'Spec', 'Router Id', 'Status' - ) + columns = ('id', 'name', 'spec', 'router_id', 'status') data = [] for s in objects: data.append( - (s.id, s.name, s.souter_id, s.status, s.description, s.admin_state_up, s.tenant_id, s.spec, s.created_at)) + (s.id, s.name, s.spec, s.router_id, s.status)) def setUp(self): super(TestListNatGateways, self).setUp() @@ -68,45 +62,48 @@ def test_list_args(self): '--limit', '1', '--id', '2', '--name', '3', - '--tenant-id', 'abc', - '--description', 'test', - '--spec', '1', + '--project-id', '4', + '--spec', '5', '--router-id', '6', '--internal-network-id', '7', - '--admin-state-up', 'true', - '--created-at', '20', + '--admin-state-up', '8', + '--created-at', '9', + '--status', '10' ] verifylist = [ ('limit', 1), ('id', '2'), ('name', '3'), - ('project_id', 'abc'), - ('description', 'test'), - ('spec', '1'), + ('tenant_id', '4'), + ('spec', '5'), ('router_id', '6'), ('internal_network_id', '7'), - ('admin_state_up', 'true'), - ('created_at', '20'), + ('admin_state_up', '8'), + ('created_at', '9'), + ('status', '10'), ] # Verify cm is triggered with default parameters parsed_args = self.check_parser(self.cmd, arglist, verifylist) + # Set the response + self.client.api_mock.side_effect = [self.objects] + # Trigger the action columns, data = self.cmd.take_action(parsed_args) self.client.api_mock.assert_called_with( - limit='1', + limit=1, id='2', name='3', - project_id='abc', - description=test, - spec='1', + tenant_id='4', + spec='5', router_id='6', internal_network_id='7', - admin_state_up='true', - created_at='20' + admin_state_up='8', + created_at='9', + status='10', ) @@ -115,7 +112,16 @@ class TestShowNatGateway(fakes.TestNat): _data = fakes.FakeNatGateway.create_one() columns = ( - 'id', 'name', 'internal network id', 'spec', 'router id', 'tenant id', 'status', 'description', 'admin state up' + 'admin_state_up', + 'created_at', + 'description', + 'id', + 'internal_network_id', + 'name', + 'project_id', + 'router_id', + 'spec', + 'status' ) data = fakes.gen_data(_data, columns) @@ -133,7 +139,7 @@ def test_show(self): ] verifylist = [ - ('gateway', 'test_gateway'), + ('nat_gateway', 'test_gateway'), ] # Verify cm is triggered with default parameters @@ -141,8 +147,7 @@ def test_show(self): # Trigger the action columns, data = self.cmd.take_action(parsed_args) - self.client.get_gateway.assert_called_with('test_gateway', - ignore_missing=False) + self.client.get_gateway.assert_called_with('test_gateway') self.assertEqual(self.columns, columns) self.assertEqual(self.data, data) @@ -175,6 +180,6 @@ def test_delete(self): # Trigger the action self.cmd.take_action(parsed_args) - self.client.get_gateway.assert_called_with('nat_gateway_id_or_name') + self.client.get_gateway.assert_called_with('test_gateway') self.client.delete_gateway.assert_called_with(self.data.id) diff --git a/otcextensions/tests/unit/osclient/nat/v2/test_snat.py b/otcextensions/tests/unit/osclient/nat/v2/test_snat.py index fba0db940..c160e3f54 100644 --- a/otcextensions/tests/unit/osclient/nat/v2/test_snat.py +++ b/otcextensions/tests/unit/osclient/nat/v2/test_snat.py @@ -40,14 +40,14 @@ class TestListSnatRules(fakes.TestNat): data = [] for s in objects: - data.append(( + data.append( s.id, s.nat_gateway_id, s.network_id, s.cidr, s.floating_ip_address, s.status - )) + ) def setUp(self): super(TestListSnatRules, self).setUp() @@ -97,7 +97,7 @@ def test_list_args(self): ('id', '2'), ('nat_gateway_id', '3'), ('network_id', '4'), - ('project_id', '5'), + ('tenant_id', '5'), ('cidr', '6'), ('source_type', '7'), ('floating_ip_id', '8'), @@ -121,7 +121,7 @@ def test_list_args(self): id='2', nat_gateway_id='3', network_id='4', - project_id='5', + tenant_id='5', cidr='6', source_type='7', floating_ip_id='8', @@ -132,60 +132,6 @@ def test_list_args(self): ) -class TestCreateSnatRule(fakes.TestNat): - - _data = fakes.FakeSnatRule.create_one() - - columns = ( - 'admin_state_up', - 'cidr', - 'created_at', - 'floating_ip_address', - 'floating_ip_id', - 'id', - 'nat_gateway_id', - 'network_id', - 'project_id', - 'source_type', - 'status' - ) - - data = fakes.gen_data(_data, columns) - - def setUp(self): - super(TestCreateSnatRule, self).setUp() - - self.cmd = snat.CreateSnatRule(self.app, None) - - self.client.create_snat_rule = mock.Mock(return_value=self._data) - - def test_create(self): - arglist = [ - '--nat-gateway-id', 'test-nat-uuid', - '--floating-ip-id', 'test-floating-ip-uuid', - '--network-id', 'test-network-uuid', - ] - - verifylist = [ - ('nat_gateway_id', 'test-nat-uuid'), - ('floating_ip_id', 'test-floating-ip-uuid'), - ('network_id', 'test-network-uuid'), - ] - - # Verify cm is triggered with default parameters - parsed_args = self.check_parser(self.cmd, arglist, verifylist) - - # Trigger the action - columns, data = self.cmd.take_action(parsed_args) - self.client.create_snat_rule.assert_called_with( - nat_gateway_id='test-nat-uuid', - floating_ip_id='test-floating-ip-uuid', - network_id='test-network-uuid') - - self.assertEqual(self.columns, columns) - self.assertEqual(self.data, data) - - class TestShowSnatRule(fakes.TestNat): _data = fakes.FakeSnatRule.create_one() @@ -219,7 +165,7 @@ def test_show(self): ] verifylist = [ - ('snat', 'test_snat_rule_id'), + ('snat_rule_id', 'test_snat_rule_id'), ] # Verify cm is triggered with default parameters @@ -251,7 +197,7 @@ def test_delete(self): ] verifylist = [ - ('snat', 'test_snat_rule_id'), + ('snat_rule_id', 'test_snat_rule_id'), ] # Verify cm is triggered with default parameters From 88b55f9ea5cef79ad0b8e8e957128373e19903e7 Mon Sep 17 00:00:00 2001 From: Vineet Pruthi Date: Tue, 4 Feb 2020 01:09:45 +0000 Subject: [PATCH 43/73] Minor fix in unit test --- otcextensions/tests/unit/osclient/nat/v2/test_snat.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/otcextensions/tests/unit/osclient/nat/v2/test_snat.py b/otcextensions/tests/unit/osclient/nat/v2/test_snat.py index c160e3f54..a9b739b8d 100644 --- a/otcextensions/tests/unit/osclient/nat/v2/test_snat.py +++ b/otcextensions/tests/unit/osclient/nat/v2/test_snat.py @@ -40,14 +40,14 @@ class TestListSnatRules(fakes.TestNat): data = [] for s in objects: - data.append( + data.append(( s.id, s.nat_gateway_id, s.network_id, s.cidr, s.floating_ip_address, s.status - ) + )) def setUp(self): super(TestListSnatRules, self).setUp() From e6de105861f4f672245810bfdea17b155885a9cb Mon Sep 17 00:00:00 2001 From: Vineet Pruthi Date: Wed, 19 Feb 2020 11:11:22 +0000 Subject: [PATCH 44/73] Adding functional tests for nat_gateway --- otcextensions/osclient/nat/v2/gateway.py | 8 ++--- .../osclient/nat/v2/test_nat_gateway.py | 29 +++++++++---------- .../unit/osclient/nat/v2/test_gateway.py | 8 ++--- 3 files changed, 21 insertions(+), 24 deletions(-) diff --git a/otcextensions/osclient/nat/v2/gateway.py b/otcextensions/osclient/nat/v2/gateway.py index 14bfd14cb..7db142c63 100644 --- a/otcextensions/osclient/nat/v2/gateway.py +++ b/otcextensions/osclient/nat/v2/gateway.py @@ -122,7 +122,7 @@ def get_parser(self, prog_name): def take_action(self, parsed_args): client = self.app.client_manager.nat - obj = client.get_gateway(parsed_args.nat_gateway) + obj = client.find_gateway(parsed_args.nat_gateway) display_columns, columns = _get_columns(obj) data = utils.get_item_properties(obj, columns) @@ -214,7 +214,7 @@ def take_action(self, parsed_args): for arg in args_list: if getattr(parsed_args, arg): attrs[arg] = getattr(parsed_args, arg) - nat_gateway = client.get_gateway(parsed_args.nat_gateway) + nat_gateway = client.find_gateway(parsed_args.nat_gateway) obj = client.update_gateway(nat_gateway.id, **attrs) @@ -240,5 +240,5 @@ def get_parser(self, prog_name): def take_action(self, parsed_args): client = self.app.client_manager.nat - nat_gateway = client.get_gateway(parsed_args.nat_gateway) - return client.delete_gateway(nat_gateway.id) + nat_gateway = client.find_gateway(parsed_args.nat_gateway) + client.delete_gateway(nat_gateway.id) diff --git a/otcextensions/tests/functional/osclient/nat/v2/test_nat_gateway.py b/otcextensions/tests/functional/osclient/nat/v2/test_nat_gateway.py index a0f78e0a0..9d861e034 100644 --- a/otcextensions/tests/functional/osclient/nat/v2/test_nat_gateway.py +++ b/otcextensions/tests/functional/osclient/nat/v2/test_nat_gateway.py @@ -21,10 +21,10 @@ class TestNatGateway(base.TestCase): UUID = uuid.uuid4().hex[:8] ROUTER_NAME = 'sdk-test-router-' + UUID - NETWORK_NAME = 'sdk-test-net-' + UUID + NET_NAME = 'sdk-test-net-' + UUID SUBNET_NAME = 'sdk-test-subnet-' + UUID ROUTER_ID = None - NETWORK_ID = None + NET_ID = None NAT_NAME = 'os-cli-test-' + UUID NAT_ID = None @@ -38,11 +38,10 @@ def test_02_gat_gateway_list_filters(self): self.openstack( 'nat gateway list ' '--limit 1 --id 2 ' - '--name 3 --spec 4 ' - '--router-id 5 ' - '--internal-network-id 6 ' - '--project-id 7 ' - '--status active ' + '--name 3 --spec 1 ' + '--router-id 123asd ' + '--internal-network-id 123qwe ' + '--status Active ' '--admin-state-up True ' ) @@ -55,7 +54,7 @@ def test_03_nat_gateway_create(self): ' --spec {spec} -f json'.format( name=self.NAT_NAME, router_id=self.ROUTER_ID, - net_id=self.NETWORK_ID, + net_id=self.NET_ID, description='OTCE Lib Test', spec=1) )) @@ -119,7 +118,6 @@ def test_09_nat_gateway_update_by_id(self): def test_10_nat_gateway_update_by_name(self): name = 'os-cli-test-' + self.UUID description = "otce cli test nat" - spec = '2' json_output = json.loads(self.openstack( 'nat gateway update {nat_name} ' '--name {name} ' @@ -128,12 +126,11 @@ def test_10_nat_gateway_update_by_name(self): '-f json'.format( nat_name=self.NAT_NAME, name=name, - spec=spec, + spec=2, desc=description) )) self.assertEqual(json_output['name'], name) self.assertEqual(json_output['description'], description) - self.assertEqual(json_output['spec'], spec) TestNatGateway.NAT_NAME = json_output['name'] def test_11_nat_gateway_delete(self): @@ -144,15 +141,15 @@ def _initialize_network(self): router = json.loads(self.openstack( 'router create -f json ' + self.ROUTER_NAME )) - network = json.loads(self.openstack( - 'network create -f json ' + self.NETWORK_NAME + net = json.loads(self.openstack( + 'network create -f json ' + self.NET_NAME )) self.openstack( 'subnet create {subnet} -f json ' '--network {net} ' '--subnet-range 192.168.0.0/24 '.format( subnet=self.SUBNET_NAME, - net=self.NETWORK_NAME + net=self.NET_NAME )) self.openstack( @@ -164,7 +161,7 @@ def _initialize_network(self): ) TestNatGateway.ROUTER_ID = router['id'] - TestNatGateway.NETWORK_ID = network['id'] + TestNatGateway.NET_ID = net['id'] def _denitialize_network(self): self.openstack( @@ -178,7 +175,7 @@ def _denitialize_network(self): 'subnet delete ' + self.SUBNET_NAME ) self.openstack( - 'network delete ' + self.NETWORK_NAME + 'network delete ' + self.NET_NAME ) self.openstack( 'router delete ' + self.ROUTER_NAME diff --git a/otcextensions/tests/unit/osclient/nat/v2/test_gateway.py b/otcextensions/tests/unit/osclient/nat/v2/test_gateway.py index e5487d1c5..4dafce406 100644 --- a/otcextensions/tests/unit/osclient/nat/v2/test_gateway.py +++ b/otcextensions/tests/unit/osclient/nat/v2/test_gateway.py @@ -131,7 +131,7 @@ def setUp(self): self.cmd = gateway.ShowNatGateway(self.app, None) - self.client.get_gateway = mock.Mock(return_value=self._data) + self.client.find_gateway = mock.Mock(return_value=self._data) def test_show(self): arglist = [ @@ -147,7 +147,7 @@ def test_show(self): # Trigger the action columns, data = self.cmd.take_action(parsed_args) - self.client.get_gateway.assert_called_with('test_gateway') + self.client.find_gateway.assert_called_with('test_gateway') self.assertEqual(self.columns, columns) self.assertEqual(self.data, data) @@ -162,7 +162,7 @@ def setUp(self): self.cmd = gateway.DeleteNatGateway(self.app, None) - self.client.get_gateway = mock.Mock(return_value=self.data) + self.client.find_gateway = mock.Mock(return_value=self.data) self.client.delete_gateway = mock.Mock(return_value=self.data) def test_delete(self): @@ -180,6 +180,6 @@ def test_delete(self): # Trigger the action self.cmd.take_action(parsed_args) - self.client.get_gateway.assert_called_with('test_gateway') + self.client.find_gateway.assert_called_with('test_gateway') self.client.delete_gateway.assert_called_with(self.data.id) From dabdc972e1a38b71bc5194b01927e2024f4eeb2b Mon Sep 17 00:00:00 2001 From: "T. Schreiber" Date: Tue, 12 Nov 2019 10:05:37 +0000 Subject: [PATCH 45/73] initial nat gateway branche --- otcextensions/sdk/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/otcextensions/sdk/__init__.py b/otcextensions/sdk/__init__.py index 8f318507d..ec60383f8 100644 --- a/otcextensions/sdk/__init__.py +++ b/otcextensions/sdk/__init__.py @@ -259,6 +259,7 @@ def load(conn, **kwargs): if service['service_type'] in conn._proxies: del conn._proxies[service['service_type']] # attr = getattr(conn, service_name) + # print(hasattr(conn, service_name)) # delattr(conn, service['service_type']) sd = _get_descriptor(service_name) From ef692f02a7066fff75cd2bee859078807f56667c Mon Sep 17 00:00:00 2001 From: Vineet Pruthi Date: Wed, 29 Jan 2020 10:53:44 +0000 Subject: [PATCH 46/73] Adding osclient code for nat --- otcextensions/osclient/nat/v2/dnat.py | 29 +++-- otcextensions/osclient/nat/v2/gateway.py | 34 +++-- otcextensions/osclient/nat/v2/snat.py | 34 ++--- .../unit/osclient/nat/v2/test_gateway.py | 118 +++++++++++++++++- 4 files changed, 171 insertions(+), 44 deletions(-) diff --git a/otcextensions/osclient/nat/v2/dnat.py b/otcextensions/osclient/nat/v2/dnat.py index 813fd860f..e41a8c7fa 100644 --- a/otcextensions/osclient/nat/v2/dnat.py +++ b/otcextensions/osclient/nat/v2/dnat.py @@ -55,8 +55,7 @@ def get_parser(self, prog_name): help=_('Limit to fetch number of records.')) parser.add_argument( '--project-id', - metavar='', - dest='tenant_id', + metavar='', help=_('Specifies the project ID.')) parser.add_argument( '--nat-gateway-id', @@ -114,7 +113,7 @@ def take_action(self, parsed_args): args_list = [ 'id', 'limit', - 'tenant_id', + 'project_id', 'nat_gateway_id', 'port_id', 'private_ip', @@ -131,7 +130,6 @@ def take_action(self, parsed_args): for arg in args_list: if getattr(parsed_args, arg): attrs[arg] = getattr(parsed_args, arg) - data = client.dnat_rules(**attrs) return ( @@ -149,15 +147,15 @@ class ShowDnatRule(command.ShowOne): def get_parser(self, prog_name): parser = super(ShowDnatRule, self).get_parser(prog_name) parser.add_argument( - 'dnat_rule_id', - metavar='', + 'dnat', + metavar='', help=_('Specifies the ID of the SNAT Rule'), ) return parser def take_action(self, parsed_args): client = self.app.client_manager.nat - obj = client.get_dnat_rule(parsed_args.dnat_rule_id) + obj = client.get_dnat_rule(parsed_args.dnat) display_columns, columns = _get_columns(obj) data = utils.get_item_properties(obj, columns) @@ -171,7 +169,8 @@ class CreateDnatRule(command.ShowOne): def get_parser(self, prog_name): parser = super(CreateDnatRule, self).get_parser(prog_name) parser.add_argument( - 'nat_gateway_id', + '--nat-gateway-id', + required=True, metavar="", help=_("Specifies the ID of the NAT gateway")) parser.add_argument( @@ -186,20 +185,24 @@ def get_parser(self, prog_name): parser.add_argument( '--internal-service-port', metavar='', + required=True, help=_('Specifies port used by ECSs or BMSs toprovide ' 'services for external systems.')) parser.add_argument( - 'floating_ip_id', + '--floating-ip-id', metavar="", + required=True, help=_('Specifies the EIP ID. Multiple EIPs are ' 'separated using commas')) parser.add_argument( '--external-service-port', metavar='', + required=True, help=_('Specifies the port for providing external services.')) parser.add_argument( '--protocol', metavar='', + required=True, help=_('Specifies the protocol type.')) return parser @@ -236,8 +239,8 @@ class DeleteDnatRule(command.Command): def get_parser(self, prog_name): parser = super(DeleteDnatRule, self).get_parser(prog_name) parser.add_argument( - 'dnat_rule_id', - metavar='', + 'dnat', + metavar='', help=_('Specifies the ID of the DNAT Rule'), ) @@ -245,5 +248,5 @@ def get_parser(self, prog_name): def take_action(self, parsed_args): client = self.app.client_manager.nat - dnat_rule = client.get_dnat_rule(parsed_args.dnat_rule_id) - return client.delete_dnat_rule(dnat_rule.id) + dnat_rule = client.get_dnat_rule(parsed_args.dnat) + client.delete_dnat_rule(dnat_rule.id) diff --git a/otcextensions/osclient/nat/v2/gateway.py b/otcextensions/osclient/nat/v2/gateway.py index 7db142c63..c402c162b 100644 --- a/otcextensions/osclient/nat/v2/gateway.py +++ b/otcextensions/osclient/nat/v2/gateway.py @@ -47,8 +47,7 @@ def get_parser(self, prog_name): help=_('Limit to fetch number of records.')) parser.add_argument( '--project-id', - metavar='', - dest='tenant_id', + metavar='', help=_('Specifies the project ID.')) parser.add_argument( '--name', @@ -89,7 +88,7 @@ def take_action(self, parsed_args): args_list = [ 'id', 'limit', - 'tenant_id', + 'project_id', 'name', 'spec', 'router_id', @@ -114,15 +113,15 @@ class ShowNatGateway(command.ShowOne): def get_parser(self, prog_name): parser = super(ShowNatGateway, self).get_parser(prog_name) parser.add_argument( - 'nat_gateway', - metavar='', + 'gateway', + metavar='', help=_('Specifies the ID of the NAT Gateway.'), ) return parser def take_action(self, parsed_args): client = self.app.client_manager.nat - obj = client.find_gateway(parsed_args.nat_gateway) + obj = client.find_gateway(parsed_args.gateway) display_columns, columns = _get_columns(obj) data = utils.get_item_properties(obj, columns) @@ -146,14 +145,23 @@ def get_parser(self, prog_name): parser.add_argument( '--spec', metavar="", - help=_("Specifies the type of the NAT gateway.")) + required=True, + help=_( + "Specifies the type of the NAT gateway." + "\n1: small type, which supports up to 10,000 " + "SNAT connections.\n2: medium type, which supports " + "up to 50,000 SNAT connections.\n3: large type, which " + "supports up to 200,000 SNAT connections.\n4: extra-large " + "type, which supports up to 1,000,000 SNAT connections.")) parser.add_argument( '--router-id', metavar="", + required=True, help=_("Specifies the VPC ID")) parser.add_argument( '--internal-network-id', metavar="", + required=True, help=_("Specifies the network ID of thedownstream interface " "(the next hop ofthe DVR) of the NAT gateway.")) @@ -187,8 +195,8 @@ class UpdateNatGateway(command.ShowOne): def get_parser(self, prog_name): parser = super(UpdateNatGateway, self).get_parser(prog_name) parser.add_argument( - 'nat_gateway', - metavar='', + 'gateway', + metavar='', help=_('Specifies the Name or ID of the NAT Gateway.'), ) parser.add_argument( @@ -214,7 +222,7 @@ def take_action(self, parsed_args): for arg in args_list: if getattr(parsed_args, arg): attrs[arg] = getattr(parsed_args, arg) - nat_gateway = client.find_gateway(parsed_args.nat_gateway) + nat_gateway = client.find_gateway(parsed_args.gateway) obj = client.update_gateway(nat_gateway.id, **attrs) @@ -231,8 +239,8 @@ class DeleteNatGateway(command.Command): def get_parser(self, prog_name): parser = super(DeleteNatGateway, self).get_parser(prog_name) parser.add_argument( - 'nat_gateway', - metavar='', + 'gateway', + metavar='', help=_('Specifies the Name or ID of the NAT gateway.'), ) @@ -240,5 +248,5 @@ def get_parser(self, prog_name): def take_action(self, parsed_args): client = self.app.client_manager.nat - nat_gateway = client.find_gateway(parsed_args.nat_gateway) + nat_gateway = client.find_gateway(parsed_args.gateway) client.delete_gateway(nat_gateway.id) diff --git a/otcextensions/osclient/nat/v2/snat.py b/otcextensions/osclient/nat/v2/snat.py index 4391769d5..b22ef7293 100644 --- a/otcextensions/osclient/nat/v2/snat.py +++ b/otcextensions/osclient/nat/v2/snat.py @@ -54,8 +54,7 @@ def get_parser(self, prog_name): help=_('Limit to fetch number of records.')) parser.add_argument( '--project-id', - metavar='', - dest='tenant_id', + metavar='', help=_('Specifies the project ID.')) parser.add_argument( '--nat-gateway-id', @@ -105,7 +104,7 @@ def take_action(self, parsed_args): 'id', 'limit', 'network_id', - 'tenant_id', + 'project_id', 'nat_gateway_id', 'network_id', 'cidr', @@ -137,15 +136,15 @@ class ShowSnatRule(command.ShowOne): def get_parser(self, prog_name): parser = super(ShowSnatRule, self).get_parser(prog_name) parser.add_argument( - 'snat_rule_id', - metavar='', + 'snat', + metavar='', help=_('Specifies the ID of the SNAT Rule'), ) return parser def take_action(self, parsed_args): client = self.app.client_manager.nat - obj = client.get_snat_rule(parsed_args.snat_rule_id) + obj = client.get_snat_rule(parsed_args.snat) display_columns, columns = _get_columns(obj) data = utils.get_item_properties(obj, columns) @@ -159,16 +158,18 @@ class CreateSnatRule(command.ShowOne): def get_parser(self, prog_name): parser = super(CreateSnatRule, self).get_parser(prog_name) parser.add_argument( - 'nat_gateway_id', + '--nat-gateway-id', + required=True, metavar='', help=_('Specifies the ID of the NAT gateway')) parser.add_argument( - 'floating_ip_id', + '--floating-ip-id', metavar='', + required=True, help=_('Specifies the EIP ID. Multiple EIPs ' 'are separated using commas')) parser.add_argument( - '--net-id', + '--network-id', metavar='', help=_('Specifies the network ID used by the SNAT rule. ' 'This parameter and cidr arealternative.')) @@ -180,7 +181,12 @@ def get_parser(self, prog_name): parser.add_argument( '--source-type', metavar='', - help=_('Specifies the source type.')) + help=_( + 'Specifies the source type.\n0: Either network_id ' + 'or cidr can be specified in a VPC.\n1: Only cidr ' + 'can be specified over a Direct Connect connection.' + '\nIf no value is entered, the default value 0 (VPC) ' + 'is used.')) return parser @@ -214,8 +220,8 @@ class DeleteSnatRule(command.Command): def get_parser(self, prog_name): parser = super(DeleteSnatRule, self).get_parser(prog_name) parser.add_argument( - 'snat_rule_id', - metavar='', + 'snat', + metavar='', help=_('Specifies the ID of the SNAT Rule'), ) @@ -223,5 +229,5 @@ def get_parser(self, prog_name): def take_action(self, parsed_args): client = self.app.client_manager.nat - snat_rule = client.get_snat_rule(parsed_args.snat_rule_id) - return client.delete_snat_rule(snat_rule.id) + snat_rule = client.get_snat_rule(parsed_args.snat) + client.delete_snat_rule(snat_rule.id) diff --git a/otcextensions/tests/unit/osclient/nat/v2/test_gateway.py b/otcextensions/tests/unit/osclient/nat/v2/test_gateway.py index 4dafce406..dd8dbd52b 100644 --- a/otcextensions/tests/unit/osclient/nat/v2/test_gateway.py +++ b/otcextensions/tests/unit/osclient/nat/v2/test_gateway.py @@ -75,7 +75,7 @@ def test_list_args(self): ('limit', 1), ('id', '2'), ('name', '3'), - ('tenant_id', '4'), + ('project_id', '4'), ('spec', '5'), ('router_id', '6'), ('internal_network_id', '7'), @@ -97,7 +97,7 @@ def test_list_args(self): limit=1, id='2', name='3', - tenant_id='4', + project_id='4', spec='5', router_id='6', internal_network_id='7', @@ -107,6 +107,116 @@ def test_list_args(self): ) +class TestCreateNatGateway(fakes.TestNat): + + _data = fakes.FakeNatGateway.create_one() + + columns = ( + 'admin_state_up', + 'created_at', + 'description', + 'id', + 'internal_network_id', + 'name', + 'project_id', + 'router_id', + 'spec', + 'status' + ) + + data = fakes.gen_data(_data, columns) + + def setUp(self): + super(TestCreateNatGateway, self).setUp() + + self.cmd = gateway.CreateNatGateway(self.app, None) + + self.client.create_gateway = mock.Mock(return_value=self._data) + + def test_create(self): + arglist = [ + 'test-gateway', + '--router-id', 'test-router-uuid', + '--internal-network-id', 'test-network-uuid', + '--spec', '1', + ] + verifylist = [ + ('name', 'test-gateway'), + ('router_id', 'test-router-uuid'), + ('internal_network_id', 'test-network-uuid'), + ('spec', '1'), + ] + # Verify cm is triggereg with default parameters + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + # Trigger the action + columns, data = self.cmd.take_action(parsed_args) + + self.client.create_gateway.assert_called_with( + name='test-gateway', + router_id='test-router-uuid', + internal_network_id='test-network-uuid', + spec='1' + ) + self.assertEqual(self.columns, columns) + + +class TestUpdateNatGateway(fakes.TestNat): + + _data = fakes.FakeNatGateway.create_one() + + columns = ( + 'admin_state_up', + 'created_at', + 'description', + 'id', + 'internal_network_id', + 'name', + 'project_id', + 'router_id', + 'spec', + 'status' + ) + + data = fakes.gen_data(_data, columns) + + def setUp(self): + super(TestUpdateNatGateway, self).setUp() + + self.cmd = gateway.UpdateNatGateway(self.app, None) + + self.client.find_gateway = mock.Mock(return_value=self._data) + self.client.update_gateway = mock.Mock(return_value=self._data) + + def test_update(self): + arglist = [ + 'test-gateway', + '--name', 'test-gateway-updated', + '--description', 'nat gateway updated', + '--spec', '2', + ] + verifylist = [ + ('gateway', 'test-gateway'), + ('name', 'test-gateway-updated'), + ('description', 'nat gateway updated'), + ('spec', '2'), + ] + # Verify cm is triggereg with default parameters + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + # Trigger the action + columns, data = self.cmd.take_action(parsed_args) + + self.client.find_gateway.assert_called_with('test-gateway') + self.client.update_gateway.assert_called_with( + self._data.id, + name='test-gateway-updated', + description='nat gateway updated', + spec='2' + ) + self.assertEqual(self.columns, columns) + + class TestShowNatGateway(fakes.TestNat): _data = fakes.FakeNatGateway.create_one() @@ -139,7 +249,7 @@ def test_show(self): ] verifylist = [ - ('nat_gateway', 'test_gateway'), + ('gateway', 'test_gateway'), ] # Verify cm is triggered with default parameters @@ -171,7 +281,7 @@ def test_delete(self): ] verifylist = [ - ('nat_gateway', 'test_gateway'), + ('gateway', 'test_gateway'), ] # Verify cm is triggered with default parameters From 2bd2d3e06d1e99fac3e2d12490231ada3ae5bb43 Mon Sep 17 00:00:00 2001 From: Vineet Pruthi Date: Mon, 3 Feb 2020 04:29:05 +0000 Subject: [PATCH 47/73] Fixed error and adding unit tests for osclient --- .../tests/unit/osclient/nat/v2/test_snat.py | 62 +++++++++++++++++-- 1 file changed, 58 insertions(+), 4 deletions(-) diff --git a/otcextensions/tests/unit/osclient/nat/v2/test_snat.py b/otcextensions/tests/unit/osclient/nat/v2/test_snat.py index a9b739b8d..fba0db940 100644 --- a/otcextensions/tests/unit/osclient/nat/v2/test_snat.py +++ b/otcextensions/tests/unit/osclient/nat/v2/test_snat.py @@ -97,7 +97,7 @@ def test_list_args(self): ('id', '2'), ('nat_gateway_id', '3'), ('network_id', '4'), - ('tenant_id', '5'), + ('project_id', '5'), ('cidr', '6'), ('source_type', '7'), ('floating_ip_id', '8'), @@ -121,7 +121,7 @@ def test_list_args(self): id='2', nat_gateway_id='3', network_id='4', - tenant_id='5', + project_id='5', cidr='6', source_type='7', floating_ip_id='8', @@ -132,6 +132,60 @@ def test_list_args(self): ) +class TestCreateSnatRule(fakes.TestNat): + + _data = fakes.FakeSnatRule.create_one() + + columns = ( + 'admin_state_up', + 'cidr', + 'created_at', + 'floating_ip_address', + 'floating_ip_id', + 'id', + 'nat_gateway_id', + 'network_id', + 'project_id', + 'source_type', + 'status' + ) + + data = fakes.gen_data(_data, columns) + + def setUp(self): + super(TestCreateSnatRule, self).setUp() + + self.cmd = snat.CreateSnatRule(self.app, None) + + self.client.create_snat_rule = mock.Mock(return_value=self._data) + + def test_create(self): + arglist = [ + '--nat-gateway-id', 'test-nat-uuid', + '--floating-ip-id', 'test-floating-ip-uuid', + '--network-id', 'test-network-uuid', + ] + + verifylist = [ + ('nat_gateway_id', 'test-nat-uuid'), + ('floating_ip_id', 'test-floating-ip-uuid'), + ('network_id', 'test-network-uuid'), + ] + + # Verify cm is triggered with default parameters + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + # Trigger the action + columns, data = self.cmd.take_action(parsed_args) + self.client.create_snat_rule.assert_called_with( + nat_gateway_id='test-nat-uuid', + floating_ip_id='test-floating-ip-uuid', + network_id='test-network-uuid') + + self.assertEqual(self.columns, columns) + self.assertEqual(self.data, data) + + class TestShowSnatRule(fakes.TestNat): _data = fakes.FakeSnatRule.create_one() @@ -165,7 +219,7 @@ def test_show(self): ] verifylist = [ - ('snat_rule_id', 'test_snat_rule_id'), + ('snat', 'test_snat_rule_id'), ] # Verify cm is triggered with default parameters @@ -197,7 +251,7 @@ def test_delete(self): ] verifylist = [ - ('snat_rule_id', 'test_snat_rule_id'), + ('snat', 'test_snat_rule_id'), ] # Verify cm is triggered with default parameters From 310b03a3fbdd2aa32bc2a846244d6f14529c53a0 Mon Sep 17 00:00:00 2001 From: Vineet Pruthi Date: Wed, 11 Mar 2020 03:27:04 +0000 Subject: [PATCH 48/73] Adding some more functional tests for nat --- .../osclient/nat/v2/test_dnat_rule.py | 46 ++++--------- .../osclient/nat/v2/test_snat_rule.py | 67 +++++-------------- 2 files changed, 31 insertions(+), 82 deletions(-) diff --git a/otcextensions/tests/functional/osclient/nat/v2/test_dnat_rule.py b/otcextensions/tests/functional/osclient/nat/v2/test_dnat_rule.py index 6dc7c1de4..8dc97bc3f 100644 --- a/otcextensions/tests/functional/osclient/nat/v2/test_dnat_rule.py +++ b/otcextensions/tests/functional/osclient/nat/v2/test_dnat_rule.py @@ -21,11 +21,11 @@ class TestDnatRule(base.TestCase): UUID = uuid.uuid4().hex[:8] ROUTER_NAME = 'sdk-test-router-' + UUID - NETWORK_NAME = 'sdk-test-net-' + UUID + NET_NAME = 'sdk-test-net-' + UUID SUBNET_NAME = 'sdk-test-subnet-' + UUID PORT_NAME = 'sdk-test-port-' + UUID ROUTER_ID = None - NETWORK_ID = None + NET_ID = None FLOATING_IP_ID = None PORT_ID = None @@ -50,7 +50,6 @@ def test_02_nat_dnat_rule_list_filters(self): '--floating-ip-address 8 ' '--external-service-port 9 ' '--status 10 ' - '--nat-gateway-id 11 ' '--protocol tcp ' '--admin-state-up true ' ) @@ -61,19 +60,16 @@ def test_03_nat_dnat_rule_create(self): self.assertIsNotNone(self.FLOATING_IP_ID) json_output = json.loads(self.openstack( 'nat dnat rule create ' - '--nat-gateway-id {nat_gateway_id} ' - '--floating-ip-id {floating_ip_id} ' - '--protocol {protocol} ' + '{nat_id} {floating_ip_id} ' + '--protocol TCP ' '--internal-service-port 80 ' '--external-service-port 80 ' '--private-ip {private_ip} ' '-f json'.format( - nat_gateway_id=self.NAT_ID, - protocol='TCP', + nat_id=self.NAT_ID, private_ip='192.168.0.3', floating_ip_id=self.FLOATING_IP_ID) )) - self.assertIsNotNone(json_output) TestDnatRule.DNAT_RULE_ID = json_output['id'] def test_04_nat_dnat_rule_list_by_id(self): @@ -83,30 +79,16 @@ def test_04_nat_dnat_rule_list_by_id(self): '--id ' + self.DNAT_RULE_ID )) self.assertIsNotNone(json_output) - self.assertEqual(next(iter(json_output))['Id'], self.DNAT_RULE_ID) - self.assertEqual( - next(iter(json_output))['Nat Gateway Id'], self.NAT_ID) - - def test_05_nat_dnat_rule_list_by_nat_id(self): - self.assertIsNotNone(self.DNAT_RULE_ID) - json_output = json.loads(self.openstack( - 'nat dnat rule list -f json ' - '--nat-gateway-id ' + self.NAT_ID - )) - self.assertIsNotNone(json_output) - self.assertEqual( - next(iter(json_output))['Nat Gateway Id'], self.NAT_ID) - def test_06_nat_dnat_rule_show(self): + def test_05_nat_dnat_rule_show(self): self.assertIsNotNone(self.DNAT_RULE_ID) json_output = json.loads(self.openstack( 'nat dnat rule show ' ' -f json ' + self.DNAT_RULE_ID )) self.assertIsNotNone(json_output) - self.assertEqual(json_output['id'], self.DNAT_RULE_ID) - def test_07_nat_dnat_rule_delete(self): + def test_11_nat_dnat_rule_delete(self): self.addCleanup(self._delete_nat_gateway) self.assertIsNotNone(self.NAT_ID) self.assertIsNotNone(self.DNAT_RULE_ID) @@ -122,7 +104,7 @@ def _create_nat_gateway(self): ' --spec {spec} -f json'.format( name=self.NAT_NAME, router_id=self.ROUTER_ID, - net_id=self.NETWORK_ID, + net_id=self.NET_ID, description='OTCE Lib Test', spec=1) )) @@ -136,15 +118,15 @@ def _initialize_network(self): router = json.loads(self.openstack( 'router create -f json ' + self.ROUTER_NAME )) - network = json.loads(self.openstack( - 'network create -f json ' + self.NETWORK_NAME + net = json.loads(self.openstack( + 'network create -f json ' + self.NET_NAME )) self.openstack( 'subnet create {subnet} -f json ' '--network {net} ' '--subnet-range 192.168.0.0/24 '.format( subnet=self.SUBNET_NAME, - net=self.NETWORK_NAME + net=self.NET_NAME )) self.openstack( @@ -162,7 +144,7 @@ def _initialize_network(self): )) TestDnatRule.ROUTER_ID = router['id'] - TestDnatRule.NETWORK_ID = network['id'] + TestDnatRule.NET_ID = net['id'] TestDnatRule.FLOATING_IP_ID = floating_ip['id'] port = json.loads(self.openstack( @@ -170,7 +152,7 @@ def _initialize_network(self): '--network {net_id} ' '-f json'.format( name=self.PORT_NAME, - net_id=self.NETWORK_ID) + net_id=self.NET_ID) )) TestDnatRule.PORT_ID = port['id'] @@ -189,7 +171,7 @@ def _denitialize_network(self): 'subnet delete ' + self.SUBNET_NAME ) self.openstack( - 'network delete ' + self.NETWORK_NAME + 'network delete ' + self.NET_NAME ) self.openstack( 'router delete ' + self.ROUTER_NAME diff --git a/otcextensions/tests/functional/osclient/nat/v2/test_snat_rule.py b/otcextensions/tests/functional/osclient/nat/v2/test_snat_rule.py index 7b46cc1d0..2db3379ec 100644 --- a/otcextensions/tests/functional/osclient/nat/v2/test_snat_rule.py +++ b/otcextensions/tests/functional/osclient/nat/v2/test_snat_rule.py @@ -22,10 +22,10 @@ class TestSnatRule(base.TestCase): UUID = uuid.uuid4().hex[:8] ROUTER_NAME = 'sdk-test-router-' + UUID - NETWORK_NAME = 'sdk-test-net-' + UUID + NET_NAME = 'sdk-test-net-' + UUID SUBNET_NAME = 'sdk-test-subnet-' + UUID ROUTER_ID = None - NETWORK_ID = None + NET_ID = None FLOATING_IP_ID = None NAT_NAME = 'os-cli-test-' + UUID @@ -58,14 +58,12 @@ def test_03_nat_snat_rule_create(self): self.assertIsNotNone(self.FLOATING_IP_ID) json_output = json.loads(self.openstack( 'nat snat rule create ' - '--nat-gateway-id {nat_gateway_id} ' - '--floating-ip-id {floating_ip_id} ' - '--network-id {net_id} -f json'.format( - nat_gateway_id=self.NAT_ID, + '{nat_id} {floating_ip_id} ' + '--net-id {net_id} -f json'.format( + nat_id=self.NAT_ID, floating_ip_id=self.FLOATING_IP_ID, - net_id=self.NETWORK_ID) + net_id=self.NET_ID) )) - self.assertIsNotNone(json_output) TestSnatRule.SNAT_RULE_ID = json_output['id'] def test_04_nat_snat_rule_list_by_id(self): @@ -75,30 +73,16 @@ def test_04_nat_snat_rule_list_by_id(self): '--id ' + self.SNAT_RULE_ID )) self.assertIsNotNone(json_output) - self.assertEqual(next(iter(json_output))['Id'], self.SNAT_RULE_ID) - self.assertEqual( - next(iter(json_output))['Nat Gateway Id'], self.NAT_ID) - - def test_05_nat_snat_rule_list_by_nat_id(self): - self.assertIsNotNone(self.SNAT_RULE_ID) - json_output = json.loads(self.openstack( - 'nat snat rule list -f json ' - '--nat-gateway-id ' + self.NAT_ID - )) - self.assertIsNotNone(json_output) - self.assertEqual( - next(iter(json_output))['Nat Gateway Id'], self.NAT_ID) - def test_06_nat_snat_rule_show(self): + def test_05_nat_snat_rule_show(self): self.assertIsNotNone(self.SNAT_RULE_ID) json_output = json.loads(self.openstack( 'nat snat rule show ' ' -f json ' + self.SNAT_RULE_ID )) self.assertIsNotNone(json_output) - self.assertEqual(json_output['id'], self.SNAT_RULE_ID) - def test_07_nat_snat_rule_create_for_existing_network(self): + def test_06_nat_snat_rule_create_for_existing_network(self): self.assertIsNotNone(self.NAT_ID) self.assertIsNotNone(self.FLOATING_IP_ID) self.assertRaises( @@ -106,34 +90,17 @@ def test_07_nat_snat_rule_create_for_existing_network(self): self.openstack, 'nat snat rule create ' '{nat_id} {floating_ip_id} ' - '--network-id {net_id} -f json'.format( + '--net-id {net_id} -f json'.format( nat_id=self.NAT_ID, floating_ip_id=self.FLOATING_IP_ID, - net_id=self.NETWORK_ID) + net_id=self.NET_ID) ) - def test_08_nat_snat_rule_create_cidr_source_type(self): + def test_07_nat_snat_rule_create_cidr_source_type(self): self.assertIsNotNone(self.NAT_ID) self.assertIsNotNone(self.FLOATING_IP_ID) - cidr = '192.168.5.0/24' - source_type = 1 - json_output = json.loads(self.openstack( - 'nat snat rule create ' - '--nat-gateway-id {nat_gateway_id} ' - '--floating-ip-id {floating_ip_id} ' - '--source-type {source_type} ' - '--cidr {cidr} -f json'.format( - nat_gateway_id=self.NAT_ID, - floating_ip_id=self.FLOATING_IP_ID, - source_type=source_type, - cidr=cidr) - )) - self.assertEqual(json_output['source_type'], source_type) - self.assertEqual(json_output['cidr'], cidr) - self.openstack( - 'nat snat rule delete ' + json_output['id']) - def test_09_nat_snat_rule_delete(self): + def test_11_nat_snat_rule_delete(self): self.addCleanup(self._delete_nat_gateway) self.assertIsNotNone(self.NAT_ID) self.assertIsNotNone(self.SNAT_RULE_ID) @@ -149,7 +116,7 @@ def _create_nat_gateway(self): ' --spec {spec} -f json'.format( name=self.NAT_NAME, router_id=self.ROUTER_ID, - net_id=self.NETWORK_ID, + net_id=self.NET_ID, description='OTCE Lib Test', spec=1) )) @@ -164,14 +131,14 @@ def _initialize_network(self): 'router create -f json ' + self.ROUTER_NAME )) net = json.loads(self.openstack( - 'network create -f json ' + self.NETWORK_NAME + 'network create -f json ' + self.NET_NAME )) self.openstack( 'subnet create {subnet} -f json ' '--network {net} ' '--subnet-range 192.168.0.0/24 '.format( subnet=self.SUBNET_NAME, - net=self.NETWORK_NAME + net=self.NET_NAME )) self.openstack( @@ -189,7 +156,7 @@ def _initialize_network(self): )) TestSnatRule.ROUTER_ID = router['id'] - TestSnatRule.NETWORK_ID = net['id'] + TestSnatRule.NET_ID = net['id'] TestSnatRule.FLOATING_IP_ID = floating_ip['id'] def _denitialize_network(self): @@ -204,7 +171,7 @@ def _denitialize_network(self): 'subnet delete ' + self.SUBNET_NAME ) self.openstack( - 'network delete ' + self.NETWORK_NAME + 'network delete ' + self.NET_NAME ) self.openstack( 'router delete ' + self.ROUTER_NAME From 0ec574fe5906a7ff034911d1ff3cdc217757182c Mon Sep 17 00:00:00 2001 From: Vineet Pruthi Date: Wed, 11 Mar 2020 08:30:36 +0000 Subject: [PATCH 49/73] Updated documentation for NAT --- doc/source/cli/index.rst | 1 + doc/source/cli/nat.rst | 36 +++++++++++++++ doc/source/enforcer.py | 1 + doc/source/user/guides/nat.rst | 4 ++ doc/source/user/proxies/nat_v2.rst | 48 ++++++++++++++++++++ doc/source/user/resources/nat/index.rst | 9 ++++ doc/source/user/resources/nat/v2/dnat.rst | 13 ++++++ doc/source/user/resources/nat/v2/gateway.rst | 13 ++++++ doc/source/user/resources/nat/v2/snat.rst | 13 ++++++ 9 files changed, 138 insertions(+) create mode 100644 doc/source/cli/nat.rst create mode 100644 doc/source/user/guides/nat.rst create mode 100644 doc/source/user/proxies/nat_v2.rst create mode 100644 doc/source/user/resources/nat/index.rst create mode 100644 doc/source/user/resources/nat/v2/dnat.rst create mode 100644 doc/source/user/resources/nat/v2/gateway.rst create mode 100644 doc/source/user/resources/nat/v2/snat.rst diff --git a/doc/source/cli/index.rst b/doc/source/cli/index.rst index 524564ba6..02343465b 100644 --- a/doc/source/cli/index.rst +++ b/doc/source/cli/index.rst @@ -14,6 +14,7 @@ OpenStackClient CLI Usage dns.rst rds.rst kms.rst + nat.rst load_balancer.rst obs.rst volume_backup.rst diff --git a/doc/source/cli/nat.rst b/doc/source/cli/nat.rst new file mode 100644 index 000000000..f13c377df --- /dev/null +++ b/doc/source/cli/nat.rst @@ -0,0 +1,36 @@ +========================================== +Database service (rds) command-line client +========================================== + +The RDS client is the command-line interface (CLI) for +the Database service (RDS) API and its extensions. + +For help on a specific `nat` command, enter: + +.. code-block:: console + + $ openstack nat help SUBCOMMAND + +.. _gateway: + +NAT Gateway operations +-------------------- + +.. autoprogram-cliff:: openstack.nat.v2 + :command: nat gateway * + +.. _snat: + +SNAT Rule operations +----------------- + +.. autoprogram-cliff:: openstack.nat.v2 + :command: nat snat * + +.. _dnat: + +DNAT Rule operations +------------------- + +.. autoprogram-cliff:: openstack.nat.v2 + :command: nat dnat * diff --git a/doc/source/enforcer.py b/doc/source/enforcer.py index 7c6d46953..87f472bce 100644 --- a/doc/source/enforcer.py +++ b/doc/source/enforcer.py @@ -50,6 +50,7 @@ def get_proxy_methods(): "otcextensions.sdk.obs.v1._proxy", "otcextensions.sdk.rds.v1._proxy", "otcextensions.sdk.rds.v3._proxy", + "otcextensions.sdk.nat.v2._proxy", "otcextensions.sdk.volume_backup.v2._proxy" ] diff --git a/doc/source/user/guides/nat.rst b/doc/source/user/guides/nat.rst new file mode 100644 index 000000000..8553150ba --- /dev/null +++ b/doc/source/user/guides/nat.rst @@ -0,0 +1,4 @@ +Using OTC NAT +============= + +.. TODO(agoncharov): Implement this guide diff --git a/doc/source/user/proxies/nat_v2.rst b/doc/source/user/proxies/nat_v2.rst new file mode 100644 index 000000000..7ec2c4df3 --- /dev/null +++ b/doc/source/user/proxies/nat_v2.rst @@ -0,0 +1,48 @@ +Database NAT API +================ + +For details on how to use database, see :doc:`/user/guides/rds` + +.. automodule:: otcextensions.sdk.nat.v2._proxy + +The NAT Class +-------------- + +The NAT high-level interface is available through the ``nat`` member of a +:class:`~openstack.connection.Connection` object. The ``nat`` member will only +be added if the ``otcextensions.sdk.register_otc_extensions(conn)`` method is +called. + +NAT Gateway Operations +^^^^^^^^^^^^^^^^^^^^^^ + +.. autoclass:: otcextensions.sdk.nat.v2._proxy.Proxy + + .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.create_gateway + .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.update_gateway + .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.delete_gateway + .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.get_gateway + .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.find_gateway + .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.gateways + + +NAT Snat Rule Operations +^^^^^^^^^^^^^^^^^^^^^^^^ + +.. autoclass:: otcextensions.sdk.nat.v2._proxy.Proxy + + .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.create_snat_rule + .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.delete_snat_rule + .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.get_snat_rule + .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.delete_snat_rule + + +NAT Dnat Rule Operations +^^^^^^^^^^^^^^^^^^^^^^^^ + +.. autoclass:: otcextensions.sdk.nat.v2._proxy.Proxy + + .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.create_dnat_rule + .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.delete_dnat_rule + .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.get_dnat_rule + .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.delete_dnat_rule diff --git a/doc/source/user/resources/nat/index.rst b/doc/source/user/resources/nat/index.rst new file mode 100644 index 000000000..712e949da --- /dev/null +++ b/doc/source/user/resources/nat/index.rst @@ -0,0 +1,9 @@ +NAT Resources +============= + +.. toctree:: + :maxdepth: 1 + + v2/gateway + v2/snat + v2/dnat diff --git a/doc/source/user/resources/nat/v2/dnat.rst b/doc/source/user/resources/nat/v2/dnat.rst new file mode 100644 index 000000000..6b26243ee --- /dev/null +++ b/doc/source/user/resources/nat/v2/dnat.rst @@ -0,0 +1,13 @@ +otcextensions.sdk.nat.v2.dnat +============================= + +.. automodule:: otcextensions.sdk.nat.v2.dnat + +The Dnat Class +-------------- + +The ``Dnat`` class inherits from +:class:`~otcextensions.sdk.sdk_resource.Resource`. + +.. autoclass:: otcextensions.sdk.nat.v2.dnat.Dnat + :members: diff --git a/doc/source/user/resources/nat/v2/gateway.rst b/doc/source/user/resources/nat/v2/gateway.rst new file mode 100644 index 000000000..8d30e9838 --- /dev/null +++ b/doc/source/user/resources/nat/v2/gateway.rst @@ -0,0 +1,13 @@ +otcextensions.sdk.nat.v2.gateway +================================ + +.. automodule:: otcextensions.sdk.nat.v2.gateway + +The Instance Class +------------------ + +The ``Gateway`` class inherits from +:class:`~otcextensions.sdk.sdk_resource.Resource`. + +.. autoclass:: otcextensions.sdk.nat.v2.gateway.Gateway + :members: diff --git a/doc/source/user/resources/nat/v2/snat.rst b/doc/source/user/resources/nat/v2/snat.rst new file mode 100644 index 000000000..ea55439ee --- /dev/null +++ b/doc/source/user/resources/nat/v2/snat.rst @@ -0,0 +1,13 @@ +otcextensions.sdk.nat.v2.snat +============================= + +.. automodule:: otcextensions.sdk.nat.v2.snat + +The Instance Class +------------------ + +The ``Dnat`` class inherits from +:class:`~otcextensions.sdk.sdk_resource.Resource`. + +.. autoclass:: otcextensions.sdk.nat.v2.snat.Snat + :members: From a9329d7282960d3ed62c8471c00b3a10abf4415d Mon Sep 17 00:00:00 2001 From: Vineet Pruthi Date: Wed, 11 Mar 2020 09:13:31 +0000 Subject: [PATCH 50/73] Fixed nat.rst erros --- doc/source/cli/nat.rst | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/doc/source/cli/nat.rst b/doc/source/cli/nat.rst index f13c377df..96b1fe5ae 100644 --- a/doc/source/cli/nat.rst +++ b/doc/source/cli/nat.rst @@ -1,9 +1,9 @@ -========================================== -Database service (rds) command-line client -========================================== +===================================================== +Network Address Translation (nat) command-line client +===================================================== -The RDS client is the command-line interface (CLI) for -the Database service (RDS) API and its extensions. +The NAT client is the command-line interface (CLI) for +the Database service (NAT) API and its extensions. For help on a specific `nat` command, enter: @@ -14,7 +14,7 @@ For help on a specific `nat` command, enter: .. _gateway: NAT Gateway operations --------------------- +---------------------- .. autoprogram-cliff:: openstack.nat.v2 :command: nat gateway * @@ -22,7 +22,7 @@ NAT Gateway operations .. _snat: SNAT Rule operations ------------------ +-------------------- .. autoprogram-cliff:: openstack.nat.v2 :command: nat snat * @@ -30,7 +30,7 @@ SNAT Rule operations .. _dnat: DNAT Rule operations -------------------- +-------------------- .. autoprogram-cliff:: openstack.nat.v2 :command: nat dnat * From e827fb312b15c6ee9614ef5143bf627bd1612399 Mon Sep 17 00:00:00 2001 From: Vineet Pruthi Date: Thu, 12 Mar 2020 10:21:45 +0000 Subject: [PATCH 51/73] Updated Functional Tests --- .../osclient/nat/v2/test_dnat_rule.py | 20 +++++++++-- .../osclient/nat/v2/test_snat_rule.py | 36 ++++++++++++++++--- 2 files changed, 50 insertions(+), 6 deletions(-) diff --git a/otcextensions/tests/functional/osclient/nat/v2/test_dnat_rule.py b/otcextensions/tests/functional/osclient/nat/v2/test_dnat_rule.py index 8dc97bc3f..837f2f319 100644 --- a/otcextensions/tests/functional/osclient/nat/v2/test_dnat_rule.py +++ b/otcextensions/tests/functional/osclient/nat/v2/test_dnat_rule.py @@ -50,6 +50,7 @@ def test_02_nat_dnat_rule_list_filters(self): '--floating-ip-address 8 ' '--external-service-port 9 ' '--status 10 ' + '--nat-gateway-id 11 ' '--protocol tcp ' '--admin-state-up true ' ) @@ -70,6 +71,7 @@ def test_03_nat_dnat_rule_create(self): private_ip='192.168.0.3', floating_ip_id=self.FLOATING_IP_ID) )) + self.assertIsNotNone(json_output) TestDnatRule.DNAT_RULE_ID = json_output['id'] def test_04_nat_dnat_rule_list_by_id(self): @@ -79,16 +81,30 @@ def test_04_nat_dnat_rule_list_by_id(self): '--id ' + self.DNAT_RULE_ID )) self.assertIsNotNone(json_output) + self.assertEqual(next(iter(json_output))['Id'], self.DNAT_RULE_ID) + self.assertEqual( + next(iter(json_output))['Nat Gateway Id'], self.NAT_ID) + + def test_05_nat_dnat_rule_list_by_nat_id(self): + self.assertIsNotNone(self.DNAT_RULE_ID) + json_output = json.loads(self.openstack( + 'nat dnat rule list -f json ' + '--nat-gateway-id ' + self.NAT_ID + )) + self.assertIsNotNone(json_output) + self.assertEqual( + next(iter(json_output))['Nat Gateway Id'], self.NAT_ID) - def test_05_nat_dnat_rule_show(self): + def test_06_nat_dnat_rule_show(self): self.assertIsNotNone(self.DNAT_RULE_ID) json_output = json.loads(self.openstack( 'nat dnat rule show ' ' -f json ' + self.DNAT_RULE_ID )) self.assertIsNotNone(json_output) + self.assertEqual(json_output['id'], self.DNAT_RULE_ID) - def test_11_nat_dnat_rule_delete(self): + def test_07_nat_dnat_rule_delete(self): self.addCleanup(self._delete_nat_gateway) self.assertIsNotNone(self.NAT_ID) self.assertIsNotNone(self.DNAT_RULE_ID) diff --git a/otcextensions/tests/functional/osclient/nat/v2/test_snat_rule.py b/otcextensions/tests/functional/osclient/nat/v2/test_snat_rule.py index 2db3379ec..4460f6235 100644 --- a/otcextensions/tests/functional/osclient/nat/v2/test_snat_rule.py +++ b/otcextensions/tests/functional/osclient/nat/v2/test_snat_rule.py @@ -64,6 +64,7 @@ def test_03_nat_snat_rule_create(self): floating_ip_id=self.FLOATING_IP_ID, net_id=self.NET_ID) )) + self.assertIsNotNone(json_output) TestSnatRule.SNAT_RULE_ID = json_output['id'] def test_04_nat_snat_rule_list_by_id(self): @@ -73,16 +74,30 @@ def test_04_nat_snat_rule_list_by_id(self): '--id ' + self.SNAT_RULE_ID )) self.assertIsNotNone(json_output) + self.assertEqual(next(iter(json_output))['Id'], self.SNAT_RULE_ID) + self.assertEqual( + next(iter(json_output))['Nat Gateway Id'], self.NAT_ID) + + def test_05_nat_snat_rule_list_by_nat_id(self): + self.assertIsNotNone(self.SNAT_RULE_ID) + json_output = json.loads(self.openstack( + 'nat snat rule list -f json ' + '--nat-gateway-id ' + self.NAT_ID + )) + self.assertIsNotNone(json_output) + self.assertEqual( + next(iter(json_output))['Nat Gateway Id'], self.NAT_ID) - def test_05_nat_snat_rule_show(self): + def test_06_nat_snat_rule_show(self): self.assertIsNotNone(self.SNAT_RULE_ID) json_output = json.loads(self.openstack( 'nat snat rule show ' ' -f json ' + self.SNAT_RULE_ID )) self.assertIsNotNone(json_output) + self.assertEqual(json_output['id'], self.SNAT_RULE_ID) - def test_06_nat_snat_rule_create_for_existing_network(self): + def test_07_nat_snat_rule_create_for_existing_network(self): self.assertIsNotNone(self.NAT_ID) self.assertIsNotNone(self.FLOATING_IP_ID) self.assertRaises( @@ -96,11 +111,24 @@ def test_06_nat_snat_rule_create_for_existing_network(self): net_id=self.NET_ID) ) - def test_07_nat_snat_rule_create_cidr_source_type(self): + def test_08_nat_snat_rule_create_cidr_source_type(self): self.assertIsNotNone(self.NAT_ID) self.assertIsNotNone(self.FLOATING_IP_ID) + json_output = json.loads(self.openstack( + 'nat snat rule create ' + '{nat_id} {floating_ip_id} ' + '--source-type {source_type} ' + '--cidr {cidr} -f json'.format( + nat_id=self.NAT_ID, + floating_ip_id=self.FLOATING_IP_ID, + source_type=1, + cidr='192.168.5.0/24') + )) + self.assertEqual(json_output['source_type'], 1) + self.openstack( + 'nat snat rule delete ' + json_output['id']) - def test_11_nat_snat_rule_delete(self): + def test_09_nat_snat_rule_delete(self): self.addCleanup(self._delete_nat_gateway) self.assertIsNotNone(self.NAT_ID) self.assertIsNotNone(self.SNAT_RULE_ID) From 3cb34bafb984301738efc8f55b6a0c1c81279c28 Mon Sep 17 00:00:00 2001 From: Vineet Pruthi Date: Mon, 16 Mar 2020 07:21:32 +0000 Subject: [PATCH 52/73] Usage of project_id in list nat functions query params --- otcextensions/sdk/nat/v2/gateway.py | 2 +- .../functional/osclient/nat/v2/test_dnat_rule.py | 9 +++++---- .../functional/osclient/nat/v2/test_nat_gateway.py | 9 +++++---- .../functional/osclient/nat/v2/test_snat_rule.py | 12 ++++++------ .../tests/unit/osclient/nat/v2/test_dnat.py | 4 ++-- 5 files changed, 19 insertions(+), 17 deletions(-) diff --git a/otcextensions/sdk/nat/v2/gateway.py b/otcextensions/sdk/nat/v2/gateway.py index bcacd7f32..b93901ebb 100644 --- a/otcextensions/sdk/nat/v2/gateway.py +++ b/otcextensions/sdk/nat/v2/gateway.py @@ -27,7 +27,7 @@ class Gateway(resource.Resource): _query_mapping = resource.QueryParameters( 'admin_state_up', 'created_at', 'description', 'id', 'internal_network_id', 'limit', 'name', 'router_id', - 'spec', 'status', 'project_id' + 'spec', 'status', 'project_id', project_id='tenant_id' ) # Properties diff --git a/otcextensions/tests/functional/osclient/nat/v2/test_dnat_rule.py b/otcextensions/tests/functional/osclient/nat/v2/test_dnat_rule.py index 837f2f319..724a6deac 100644 --- a/otcextensions/tests/functional/osclient/nat/v2/test_dnat_rule.py +++ b/otcextensions/tests/functional/osclient/nat/v2/test_dnat_rule.py @@ -60,14 +60,15 @@ def test_03_nat_dnat_rule_create(self): self.assertIsNotNone(self.PORT_ID) self.assertIsNotNone(self.FLOATING_IP_ID) json_output = json.loads(self.openstack( - 'nat dnat rule create ' - '{nat_id} {floating_ip_id} ' - '--protocol TCP ' + 'nat dnat rule create {nat_gateway_id} ' + '--floating-ip-id {floating_ip_id} ' + '--protocol {protocol} ' '--internal-service-port 80 ' '--external-service-port 80 ' '--private-ip {private_ip} ' '-f json'.format( - nat_id=self.NAT_ID, + nat_gateway_id=self.NAT_ID, + protocol='TCP', private_ip='192.168.0.3', floating_ip_id=self.FLOATING_IP_ID) )) diff --git a/otcextensions/tests/functional/osclient/nat/v2/test_nat_gateway.py b/otcextensions/tests/functional/osclient/nat/v2/test_nat_gateway.py index 9d861e034..f9d82a7d5 100644 --- a/otcextensions/tests/functional/osclient/nat/v2/test_nat_gateway.py +++ b/otcextensions/tests/functional/osclient/nat/v2/test_nat_gateway.py @@ -38,10 +38,11 @@ def test_02_gat_gateway_list_filters(self): self.openstack( 'nat gateway list ' '--limit 1 --id 2 ' - '--name 3 --spec 1 ' - '--router-id 123asd ' - '--internal-network-id 123qwe ' - '--status Active ' + '--name 3 --spec 4 ' + '--router-id 5 ' + '--internal-network-id 6 ' + '--project-id 7 ' + '--status active ' '--admin-state-up True ' ) diff --git a/otcextensions/tests/functional/osclient/nat/v2/test_snat_rule.py b/otcextensions/tests/functional/osclient/nat/v2/test_snat_rule.py index 4460f6235..dddc3fac1 100644 --- a/otcextensions/tests/functional/osclient/nat/v2/test_snat_rule.py +++ b/otcextensions/tests/functional/osclient/nat/v2/test_snat_rule.py @@ -57,10 +57,10 @@ def test_03_nat_snat_rule_create(self): self.assertIsNotNone(self.NAT_ID) self.assertIsNotNone(self.FLOATING_IP_ID) json_output = json.loads(self.openstack( - 'nat snat rule create ' - '{nat_id} {floating_ip_id} ' + 'nat snat rule create {nat_gateway_id} ' + '--floating-ip-id {floating_ip_id} ' '--net-id {net_id} -f json'.format( - nat_id=self.NAT_ID, + nat_gateway_id=self.NAT_ID, floating_ip_id=self.FLOATING_IP_ID, net_id=self.NET_ID) )) @@ -115,11 +115,11 @@ def test_08_nat_snat_rule_create_cidr_source_type(self): self.assertIsNotNone(self.NAT_ID) self.assertIsNotNone(self.FLOATING_IP_ID) json_output = json.loads(self.openstack( - 'nat snat rule create ' - '{nat_id} {floating_ip_id} ' + 'nat snat rule create {nat_gateway_id} ' + '--floating-ip-id {floating_ip_id} ' '--source-type {source_type} ' '--cidr {cidr} -f json'.format( - nat_id=self.NAT_ID, + nat_gateway_id=self.NAT_ID, floating_ip_id=self.FLOATING_IP_ID, source_type=1, cidr='192.168.5.0/24') diff --git a/otcextensions/tests/unit/osclient/nat/v2/test_dnat.py b/otcextensions/tests/unit/osclient/nat/v2/test_dnat.py index f363ccd9a..71070da7f 100644 --- a/otcextensions/tests/unit/osclient/nat/v2/test_dnat.py +++ b/otcextensions/tests/unit/osclient/nat/v2/test_dnat.py @@ -99,7 +99,7 @@ def test_list_args(self): ('limit', 1), ('id', '2'), ('nat_gateway_id', '3'), - ('tenant_id', '4'), + ('project_id', '4'), ('private_ip', '5'), ('internal_service_port', '6'), ('protocol', '7'), @@ -123,7 +123,7 @@ def test_list_args(self): limit=1, id='2', nat_gateway_id='3', - tenant_id='4', + project_id='4', private_ip='5', internal_service_port='6', protocol='7', From cd0402def0c1986e665f593c1aff001aedc47ed6 Mon Sep 17 00:00:00 2001 From: Vineet Pruthi Date: Mon, 16 Mar 2020 07:58:37 +0000 Subject: [PATCH 53/73] Updated nat_gateway_id as keyword arg --- .../tests/functional/osclient/nat/v2/test_dnat_rule.py | 3 ++- .../tests/functional/osclient/nat/v2/test_snat_rule.py | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/otcextensions/tests/functional/osclient/nat/v2/test_dnat_rule.py b/otcextensions/tests/functional/osclient/nat/v2/test_dnat_rule.py index 724a6deac..71a106493 100644 --- a/otcextensions/tests/functional/osclient/nat/v2/test_dnat_rule.py +++ b/otcextensions/tests/functional/osclient/nat/v2/test_dnat_rule.py @@ -60,7 +60,8 @@ def test_03_nat_dnat_rule_create(self): self.assertIsNotNone(self.PORT_ID) self.assertIsNotNone(self.FLOATING_IP_ID) json_output = json.loads(self.openstack( - 'nat dnat rule create {nat_gateway_id} ' + 'nat dnat rule create ' + '--nat-gateway-id {nat_gateway_id} ' '--floating-ip-id {floating_ip_id} ' '--protocol {protocol} ' '--internal-service-port 80 ' diff --git a/otcextensions/tests/functional/osclient/nat/v2/test_snat_rule.py b/otcextensions/tests/functional/osclient/nat/v2/test_snat_rule.py index dddc3fac1..638372b0e 100644 --- a/otcextensions/tests/functional/osclient/nat/v2/test_snat_rule.py +++ b/otcextensions/tests/functional/osclient/nat/v2/test_snat_rule.py @@ -57,7 +57,8 @@ def test_03_nat_snat_rule_create(self): self.assertIsNotNone(self.NAT_ID) self.assertIsNotNone(self.FLOATING_IP_ID) json_output = json.loads(self.openstack( - 'nat snat rule create {nat_gateway_id} ' + 'nat snat rule create ' + '--nat-gateway-id {nat_gateway_id} ' '--floating-ip-id {floating_ip_id} ' '--net-id {net_id} -f json'.format( nat_gateway_id=self.NAT_ID, @@ -115,7 +116,8 @@ def test_08_nat_snat_rule_create_cidr_source_type(self): self.assertIsNotNone(self.NAT_ID) self.assertIsNotNone(self.FLOATING_IP_ID) json_output = json.loads(self.openstack( - 'nat snat rule create {nat_gateway_id} ' + 'nat snat rule create ' + '--nat-gateway-id {nat_gateway_id} ' '--floating-ip-id {floating_ip_id} ' '--source-type {source_type} ' '--cidr {cidr} -f json'.format( From bfc5d25c5f7da56f869cedffaa2253f4ee825d60 Mon Sep 17 00:00:00 2001 From: Vineet Pruthi Date: Wed, 18 Mar 2020 08:46:08 +0000 Subject: [PATCH 54/73] remove python2 dependancy from tox --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index 28b0062a1..e450963fe 100644 --- a/tox.ini +++ b/tox.ini @@ -1,6 +1,6 @@ [tox] minversion = 3.1 -envlist = py27,py36,py37,pep8 +envlist = py36,py37,pep8 skipsdist = True ignore_basepython_conflict = True From 895c5016167521cf887caab4d42f90316b7ae4a7 Mon Sep 17 00:00:00 2001 From: Vineet Pruthi Date: Wed, 18 Mar 2020 10:11:31 +0000 Subject: [PATCH 55/73] Fixed unit tests with updated args --- otcextensions/tests/unit/osclient/nat/v2/test_dnat.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/otcextensions/tests/unit/osclient/nat/v2/test_dnat.py b/otcextensions/tests/unit/osclient/nat/v2/test_dnat.py index 71070da7f..96cdce9b9 100644 --- a/otcextensions/tests/unit/osclient/nat/v2/test_dnat.py +++ b/otcextensions/tests/unit/osclient/nat/v2/test_dnat.py @@ -170,7 +170,7 @@ def test_show(self): ] verifylist = [ - ('dnat_rule_id', 'test_dnat_rule_id'), + ('dnat', 'test_dnat_rule_id'), ] # Verify cm is triggered with default parameters @@ -202,7 +202,7 @@ def test_delete(self): ] verifylist = [ - ('dnat_rule_id', 'test_dnat_rule_id'), + ('dnat', 'test_dnat_rule_id'), ] # Verify cm is triggered with default parameters From b37fccb89fd160ed75ba64a1d55d97bec8b934e9 Mon Sep 17 00:00:00 2001 From: Vineet Pruthi Date: Wed, 18 Mar 2020 10:25:21 +0000 Subject: [PATCH 56/73] roll back py27 in tox.ini --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index e450963fe..28b0062a1 100644 --- a/tox.ini +++ b/tox.ini @@ -1,6 +1,6 @@ [tox] minversion = 3.1 -envlist = py36,py37,pep8 +envlist = py27,py36,py37,pep8 skipsdist = True ignore_basepython_conflict = True From 6ff8731803d4a82d1457fa46597c66b4f72853dc Mon Sep 17 00:00:00 2001 From: Vineet Pruthi Date: Thu, 19 Mar 2020 08:44:53 +0000 Subject: [PATCH 57/73] Fixed errors and remove nat documentation" --- doc/source/cli/index.rst | 1 - doc/source/cli/nat.rst | 36 ---------- doc/source/enforcer.py | 1 - doc/source/user/guides/nat.rst | 4 -- doc/source/user/proxies/nat_v2.rst | 48 -------------- doc/source/user/resources/nat/index.rst | 9 --- doc/source/user/resources/nat/v2/dnat.rst | 13 ---- doc/source/user/resources/nat/v2/gateway.rst | 13 ---- doc/source/user/resources/nat/v2/snat.rst | 13 ---- .../osclient/nat/v2/test_dnat_rule.py | 18 ++--- .../osclient/nat/v2/test_nat_gateway.py | 20 +++--- .../osclient/nat/v2/test_snat_rule.py | 31 +++++---- .../tests/unit/osclient/nat/v2/test_dnat.py | 65 +++++++++++++++++++ 13 files changed, 102 insertions(+), 170 deletions(-) delete mode 100644 doc/source/cli/nat.rst delete mode 100644 doc/source/user/guides/nat.rst delete mode 100644 doc/source/user/proxies/nat_v2.rst delete mode 100644 doc/source/user/resources/nat/index.rst delete mode 100644 doc/source/user/resources/nat/v2/dnat.rst delete mode 100644 doc/source/user/resources/nat/v2/gateway.rst delete mode 100644 doc/source/user/resources/nat/v2/snat.rst diff --git a/doc/source/cli/index.rst b/doc/source/cli/index.rst index 02343465b..524564ba6 100644 --- a/doc/source/cli/index.rst +++ b/doc/source/cli/index.rst @@ -14,7 +14,6 @@ OpenStackClient CLI Usage dns.rst rds.rst kms.rst - nat.rst load_balancer.rst obs.rst volume_backup.rst diff --git a/doc/source/cli/nat.rst b/doc/source/cli/nat.rst deleted file mode 100644 index 96b1fe5ae..000000000 --- a/doc/source/cli/nat.rst +++ /dev/null @@ -1,36 +0,0 @@ -===================================================== -Network Address Translation (nat) command-line client -===================================================== - -The NAT client is the command-line interface (CLI) for -the Database service (NAT) API and its extensions. - -For help on a specific `nat` command, enter: - -.. code-block:: console - - $ openstack nat help SUBCOMMAND - -.. _gateway: - -NAT Gateway operations ----------------------- - -.. autoprogram-cliff:: openstack.nat.v2 - :command: nat gateway * - -.. _snat: - -SNAT Rule operations --------------------- - -.. autoprogram-cliff:: openstack.nat.v2 - :command: nat snat * - -.. _dnat: - -DNAT Rule operations --------------------- - -.. autoprogram-cliff:: openstack.nat.v2 - :command: nat dnat * diff --git a/doc/source/enforcer.py b/doc/source/enforcer.py index 87f472bce..7c6d46953 100644 --- a/doc/source/enforcer.py +++ b/doc/source/enforcer.py @@ -50,7 +50,6 @@ def get_proxy_methods(): "otcextensions.sdk.obs.v1._proxy", "otcextensions.sdk.rds.v1._proxy", "otcextensions.sdk.rds.v3._proxy", - "otcextensions.sdk.nat.v2._proxy", "otcextensions.sdk.volume_backup.v2._proxy" ] diff --git a/doc/source/user/guides/nat.rst b/doc/source/user/guides/nat.rst deleted file mode 100644 index 8553150ba..000000000 --- a/doc/source/user/guides/nat.rst +++ /dev/null @@ -1,4 +0,0 @@ -Using OTC NAT -============= - -.. TODO(agoncharov): Implement this guide diff --git a/doc/source/user/proxies/nat_v2.rst b/doc/source/user/proxies/nat_v2.rst deleted file mode 100644 index 7ec2c4df3..000000000 --- a/doc/source/user/proxies/nat_v2.rst +++ /dev/null @@ -1,48 +0,0 @@ -Database NAT API -================ - -For details on how to use database, see :doc:`/user/guides/rds` - -.. automodule:: otcextensions.sdk.nat.v2._proxy - -The NAT Class --------------- - -The NAT high-level interface is available through the ``nat`` member of a -:class:`~openstack.connection.Connection` object. The ``nat`` member will only -be added if the ``otcextensions.sdk.register_otc_extensions(conn)`` method is -called. - -NAT Gateway Operations -^^^^^^^^^^^^^^^^^^^^^^ - -.. autoclass:: otcextensions.sdk.nat.v2._proxy.Proxy - - .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.create_gateway - .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.update_gateway - .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.delete_gateway - .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.get_gateway - .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.find_gateway - .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.gateways - - -NAT Snat Rule Operations -^^^^^^^^^^^^^^^^^^^^^^^^ - -.. autoclass:: otcextensions.sdk.nat.v2._proxy.Proxy - - .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.create_snat_rule - .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.delete_snat_rule - .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.get_snat_rule - .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.delete_snat_rule - - -NAT Dnat Rule Operations -^^^^^^^^^^^^^^^^^^^^^^^^ - -.. autoclass:: otcextensions.sdk.nat.v2._proxy.Proxy - - .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.create_dnat_rule - .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.delete_dnat_rule - .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.get_dnat_rule - .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.delete_dnat_rule diff --git a/doc/source/user/resources/nat/index.rst b/doc/source/user/resources/nat/index.rst deleted file mode 100644 index 712e949da..000000000 --- a/doc/source/user/resources/nat/index.rst +++ /dev/null @@ -1,9 +0,0 @@ -NAT Resources -============= - -.. toctree:: - :maxdepth: 1 - - v2/gateway - v2/snat - v2/dnat diff --git a/doc/source/user/resources/nat/v2/dnat.rst b/doc/source/user/resources/nat/v2/dnat.rst deleted file mode 100644 index 6b26243ee..000000000 --- a/doc/source/user/resources/nat/v2/dnat.rst +++ /dev/null @@ -1,13 +0,0 @@ -otcextensions.sdk.nat.v2.dnat -============================= - -.. automodule:: otcextensions.sdk.nat.v2.dnat - -The Dnat Class --------------- - -The ``Dnat`` class inherits from -:class:`~otcextensions.sdk.sdk_resource.Resource`. - -.. autoclass:: otcextensions.sdk.nat.v2.dnat.Dnat - :members: diff --git a/doc/source/user/resources/nat/v2/gateway.rst b/doc/source/user/resources/nat/v2/gateway.rst deleted file mode 100644 index 8d30e9838..000000000 --- a/doc/source/user/resources/nat/v2/gateway.rst +++ /dev/null @@ -1,13 +0,0 @@ -otcextensions.sdk.nat.v2.gateway -================================ - -.. automodule:: otcextensions.sdk.nat.v2.gateway - -The Instance Class ------------------- - -The ``Gateway`` class inherits from -:class:`~otcextensions.sdk.sdk_resource.Resource`. - -.. autoclass:: otcextensions.sdk.nat.v2.gateway.Gateway - :members: diff --git a/doc/source/user/resources/nat/v2/snat.rst b/doc/source/user/resources/nat/v2/snat.rst deleted file mode 100644 index ea55439ee..000000000 --- a/doc/source/user/resources/nat/v2/snat.rst +++ /dev/null @@ -1,13 +0,0 @@ -otcextensions.sdk.nat.v2.snat -============================= - -.. automodule:: otcextensions.sdk.nat.v2.snat - -The Instance Class ------------------- - -The ``Dnat`` class inherits from -:class:`~otcextensions.sdk.sdk_resource.Resource`. - -.. autoclass:: otcextensions.sdk.nat.v2.snat.Snat - :members: diff --git a/otcextensions/tests/functional/osclient/nat/v2/test_dnat_rule.py b/otcextensions/tests/functional/osclient/nat/v2/test_dnat_rule.py index 71a106493..6dc7c1de4 100644 --- a/otcextensions/tests/functional/osclient/nat/v2/test_dnat_rule.py +++ b/otcextensions/tests/functional/osclient/nat/v2/test_dnat_rule.py @@ -21,11 +21,11 @@ class TestDnatRule(base.TestCase): UUID = uuid.uuid4().hex[:8] ROUTER_NAME = 'sdk-test-router-' + UUID - NET_NAME = 'sdk-test-net-' + UUID + NETWORK_NAME = 'sdk-test-net-' + UUID SUBNET_NAME = 'sdk-test-subnet-' + UUID PORT_NAME = 'sdk-test-port-' + UUID ROUTER_ID = None - NET_ID = None + NETWORK_ID = None FLOATING_IP_ID = None PORT_ID = None @@ -122,7 +122,7 @@ def _create_nat_gateway(self): ' --spec {spec} -f json'.format( name=self.NAT_NAME, router_id=self.ROUTER_ID, - net_id=self.NET_ID, + net_id=self.NETWORK_ID, description='OTCE Lib Test', spec=1) )) @@ -136,15 +136,15 @@ def _initialize_network(self): router = json.loads(self.openstack( 'router create -f json ' + self.ROUTER_NAME )) - net = json.loads(self.openstack( - 'network create -f json ' + self.NET_NAME + network = json.loads(self.openstack( + 'network create -f json ' + self.NETWORK_NAME )) self.openstack( 'subnet create {subnet} -f json ' '--network {net} ' '--subnet-range 192.168.0.0/24 '.format( subnet=self.SUBNET_NAME, - net=self.NET_NAME + net=self.NETWORK_NAME )) self.openstack( @@ -162,7 +162,7 @@ def _initialize_network(self): )) TestDnatRule.ROUTER_ID = router['id'] - TestDnatRule.NET_ID = net['id'] + TestDnatRule.NETWORK_ID = network['id'] TestDnatRule.FLOATING_IP_ID = floating_ip['id'] port = json.loads(self.openstack( @@ -170,7 +170,7 @@ def _initialize_network(self): '--network {net_id} ' '-f json'.format( name=self.PORT_NAME, - net_id=self.NET_ID) + net_id=self.NETWORK_ID) )) TestDnatRule.PORT_ID = port['id'] @@ -189,7 +189,7 @@ def _denitialize_network(self): 'subnet delete ' + self.SUBNET_NAME ) self.openstack( - 'network delete ' + self.NET_NAME + 'network delete ' + self.NETWORK_NAME ) self.openstack( 'router delete ' + self.ROUTER_NAME diff --git a/otcextensions/tests/functional/osclient/nat/v2/test_nat_gateway.py b/otcextensions/tests/functional/osclient/nat/v2/test_nat_gateway.py index f9d82a7d5..a0f78e0a0 100644 --- a/otcextensions/tests/functional/osclient/nat/v2/test_nat_gateway.py +++ b/otcextensions/tests/functional/osclient/nat/v2/test_nat_gateway.py @@ -21,10 +21,10 @@ class TestNatGateway(base.TestCase): UUID = uuid.uuid4().hex[:8] ROUTER_NAME = 'sdk-test-router-' + UUID - NET_NAME = 'sdk-test-net-' + UUID + NETWORK_NAME = 'sdk-test-net-' + UUID SUBNET_NAME = 'sdk-test-subnet-' + UUID ROUTER_ID = None - NET_ID = None + NETWORK_ID = None NAT_NAME = 'os-cli-test-' + UUID NAT_ID = None @@ -55,7 +55,7 @@ def test_03_nat_gateway_create(self): ' --spec {spec} -f json'.format( name=self.NAT_NAME, router_id=self.ROUTER_ID, - net_id=self.NET_ID, + net_id=self.NETWORK_ID, description='OTCE Lib Test', spec=1) )) @@ -119,6 +119,7 @@ def test_09_nat_gateway_update_by_id(self): def test_10_nat_gateway_update_by_name(self): name = 'os-cli-test-' + self.UUID description = "otce cli test nat" + spec = '2' json_output = json.loads(self.openstack( 'nat gateway update {nat_name} ' '--name {name} ' @@ -127,11 +128,12 @@ def test_10_nat_gateway_update_by_name(self): '-f json'.format( nat_name=self.NAT_NAME, name=name, - spec=2, + spec=spec, desc=description) )) self.assertEqual(json_output['name'], name) self.assertEqual(json_output['description'], description) + self.assertEqual(json_output['spec'], spec) TestNatGateway.NAT_NAME = json_output['name'] def test_11_nat_gateway_delete(self): @@ -142,15 +144,15 @@ def _initialize_network(self): router = json.loads(self.openstack( 'router create -f json ' + self.ROUTER_NAME )) - net = json.loads(self.openstack( - 'network create -f json ' + self.NET_NAME + network = json.loads(self.openstack( + 'network create -f json ' + self.NETWORK_NAME )) self.openstack( 'subnet create {subnet} -f json ' '--network {net} ' '--subnet-range 192.168.0.0/24 '.format( subnet=self.SUBNET_NAME, - net=self.NET_NAME + net=self.NETWORK_NAME )) self.openstack( @@ -162,7 +164,7 @@ def _initialize_network(self): ) TestNatGateway.ROUTER_ID = router['id'] - TestNatGateway.NET_ID = net['id'] + TestNatGateway.NETWORK_ID = network['id'] def _denitialize_network(self): self.openstack( @@ -176,7 +178,7 @@ def _denitialize_network(self): 'subnet delete ' + self.SUBNET_NAME ) self.openstack( - 'network delete ' + self.NET_NAME + 'network delete ' + self.NETWORK_NAME ) self.openstack( 'router delete ' + self.ROUTER_NAME diff --git a/otcextensions/tests/functional/osclient/nat/v2/test_snat_rule.py b/otcextensions/tests/functional/osclient/nat/v2/test_snat_rule.py index 638372b0e..7b46cc1d0 100644 --- a/otcextensions/tests/functional/osclient/nat/v2/test_snat_rule.py +++ b/otcextensions/tests/functional/osclient/nat/v2/test_snat_rule.py @@ -22,10 +22,10 @@ class TestSnatRule(base.TestCase): UUID = uuid.uuid4().hex[:8] ROUTER_NAME = 'sdk-test-router-' + UUID - NET_NAME = 'sdk-test-net-' + UUID + NETWORK_NAME = 'sdk-test-net-' + UUID SUBNET_NAME = 'sdk-test-subnet-' + UUID ROUTER_ID = None - NET_ID = None + NETWORK_ID = None FLOATING_IP_ID = None NAT_NAME = 'os-cli-test-' + UUID @@ -60,10 +60,10 @@ def test_03_nat_snat_rule_create(self): 'nat snat rule create ' '--nat-gateway-id {nat_gateway_id} ' '--floating-ip-id {floating_ip_id} ' - '--net-id {net_id} -f json'.format( + '--network-id {net_id} -f json'.format( nat_gateway_id=self.NAT_ID, floating_ip_id=self.FLOATING_IP_ID, - net_id=self.NET_ID) + net_id=self.NETWORK_ID) )) self.assertIsNotNone(json_output) TestSnatRule.SNAT_RULE_ID = json_output['id'] @@ -106,15 +106,17 @@ def test_07_nat_snat_rule_create_for_existing_network(self): self.openstack, 'nat snat rule create ' '{nat_id} {floating_ip_id} ' - '--net-id {net_id} -f json'.format( + '--network-id {net_id} -f json'.format( nat_id=self.NAT_ID, floating_ip_id=self.FLOATING_IP_ID, - net_id=self.NET_ID) + net_id=self.NETWORK_ID) ) def test_08_nat_snat_rule_create_cidr_source_type(self): self.assertIsNotNone(self.NAT_ID) self.assertIsNotNone(self.FLOATING_IP_ID) + cidr = '192.168.5.0/24' + source_type = 1 json_output = json.loads(self.openstack( 'nat snat rule create ' '--nat-gateway-id {nat_gateway_id} ' @@ -123,10 +125,11 @@ def test_08_nat_snat_rule_create_cidr_source_type(self): '--cidr {cidr} -f json'.format( nat_gateway_id=self.NAT_ID, floating_ip_id=self.FLOATING_IP_ID, - source_type=1, - cidr='192.168.5.0/24') + source_type=source_type, + cidr=cidr) )) - self.assertEqual(json_output['source_type'], 1) + self.assertEqual(json_output['source_type'], source_type) + self.assertEqual(json_output['cidr'], cidr) self.openstack( 'nat snat rule delete ' + json_output['id']) @@ -146,7 +149,7 @@ def _create_nat_gateway(self): ' --spec {spec} -f json'.format( name=self.NAT_NAME, router_id=self.ROUTER_ID, - net_id=self.NET_ID, + net_id=self.NETWORK_ID, description='OTCE Lib Test', spec=1) )) @@ -161,14 +164,14 @@ def _initialize_network(self): 'router create -f json ' + self.ROUTER_NAME )) net = json.loads(self.openstack( - 'network create -f json ' + self.NET_NAME + 'network create -f json ' + self.NETWORK_NAME )) self.openstack( 'subnet create {subnet} -f json ' '--network {net} ' '--subnet-range 192.168.0.0/24 '.format( subnet=self.SUBNET_NAME, - net=self.NET_NAME + net=self.NETWORK_NAME )) self.openstack( @@ -186,7 +189,7 @@ def _initialize_network(self): )) TestSnatRule.ROUTER_ID = router['id'] - TestSnatRule.NET_ID = net['id'] + TestSnatRule.NETWORK_ID = net['id'] TestSnatRule.FLOATING_IP_ID = floating_ip['id'] def _denitialize_network(self): @@ -201,7 +204,7 @@ def _denitialize_network(self): 'subnet delete ' + self.SUBNET_NAME ) self.openstack( - 'network delete ' + self.NET_NAME + 'network delete ' + self.NETWORK_NAME ) self.openstack( 'router delete ' + self.ROUTER_NAME diff --git a/otcextensions/tests/unit/osclient/nat/v2/test_dnat.py b/otcextensions/tests/unit/osclient/nat/v2/test_dnat.py index 96cdce9b9..7ef4a7abc 100644 --- a/otcextensions/tests/unit/osclient/nat/v2/test_dnat.py +++ b/otcextensions/tests/unit/osclient/nat/v2/test_dnat.py @@ -184,6 +184,71 @@ def test_show(self): self.assertEqual(self.data, data) +class TestCreateDnatRule(fakes.TestNat): + + _data = fakes.FakeDnatRule.create_one() + + columns = ( + 'admin_state_up', + 'created_at', + 'external_service_port', + 'floating_ip_address', + 'floating_ip_id', + 'id', + 'internal_service_port', + 'nat_gateway_id', + 'port_id', + 'private_ip', + 'project_id', + 'protocol', + 'status' + ) + + data = fakes.gen_data(_data, columns) + + def setUp(self): + super(TestCreateDnatRule, self).setUp() + + self.cmd = dnat.CreateDnatRule(self.app, None) + + self.client.create_dnat_rule = mock.Mock(return_value=self._data) + + def test_create(self): + arglist = [ + '--nat-gateway-id', 'test-nat-uuid', + '--floating-ip-id', 'test-floating-ip-uuid', + '--protocol', 'tcp', + '--internal-service-port', '80', + '--external-service-port', '80', + '--private-ip', '192.168.0.99', + ] + + verifylist = [ + ('nat_gateway_id', 'test-nat-uuid'), + ('floating_ip_id', 'test-floating-ip-uuid'), + ('protocol', 'tcp'), + ('internal_service_port', '80'), + ('external_service_port', '80'), + ('private_ip', '192.168.0.99'), + ] + + # Verify cm is triggered with default parameters + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + # Trigger the action + columns, data = self.cmd.take_action(parsed_args) + self.client.create_dnat_rule.assert_called_with( + nat_gateway_id='test-nat-uuid', + floating_ip_id='test-floating-ip-uuid', + protocol='tcp', + internal_service_port='80', + external_service_port='80', + private_ip='192.168.0.99') + + self.assertEqual(self.columns, columns) + self.assertEqual(self.data, data) + + class TestDeleteDnatRule(fakes.TestNat): data = fakes.FakeDnatRule.create_one() From e7a30409c2d30f1f62074b28d23a00ddf5923a25 Mon Sep 17 00:00:00 2001 From: Vineet Pruthi Date: Fri, 20 Mar 2020 07:09:42 +0000 Subject: [PATCH 58/73] Removed print --- otcextensions/sdk/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/otcextensions/sdk/__init__.py b/otcextensions/sdk/__init__.py index ec60383f8..8f318507d 100644 --- a/otcextensions/sdk/__init__.py +++ b/otcextensions/sdk/__init__.py @@ -259,7 +259,6 @@ def load(conn, **kwargs): if service['service_type'] in conn._proxies: del conn._proxies[service['service_type']] # attr = getattr(conn, service_name) - # print(hasattr(conn, service_name)) # delattr(conn, service['service_type']) sd = _get_descriptor(service_name) From 6dcdf03330d0a916f4de8285ace46f31a38d30e0 Mon Sep 17 00:00:00 2001 From: Vineet Pruthi Date: Thu, 26 Mar 2020 09:53:19 +0000 Subject: [PATCH 59/73] Checkout origin/master otcextensions/sdk/__init__.py --- otcextensions/sdk/__init__.py | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/otcextensions/sdk/__init__.py b/otcextensions/sdk/__init__.py index 8f318507d..7bdb893d0 100644 --- a/otcextensions/sdk/__init__.py +++ b/otcextensions/sdk/__init__.py @@ -12,9 +12,13 @@ import importlib import os +import openstack from openstack import _log from openstack import utils +from otcextensions.sdk.compute.v2 import server +from otcextensions.common import exc + _logger = _log.setup_logging('openstack') @@ -240,6 +244,15 @@ def get_ak_sk(conn): return(ak, sk) +def patch_openstack_resources(): + openstack.compute.v2.server.Server._get_tag_struct = \ + server.Server._get_tag_struct + openstack.compute.v2.server.Server.add_tag = server.Server.add_tag + openstack.compute.v2.server.Server.remove_tag = server.Server.remove_tag + openstack.exceptions.raise_from_response = \ + exc.raise_from_response + + def load(conn, **kwargs): """Register supported OTC services and make them known to the OpenStackSDK @@ -272,15 +285,18 @@ def load(conn, **kwargs): if ep and not ep.rstrip('/').endswith('\\%(project_id)s') \ and not ep.rstrip('/').endswith('$(tenant_id)s') \ and not ep.rstrip('/').endswith(project_id): - conn.config.config[ - '_'.join([ - sd.service_type.lower().replace('-', '_'), - 'endpoint_override' - ]) - ] = utils.urljoin(ep, '%(project_id)s') + key = '_'.join([ + sd.service_type.lower().replace('-', '_'), + 'endpoint_override']) + if key not in conn.config.config: + conn.config.config[key] = utils.urljoin(ep, + '%(project_id)s') + elif service.get('set_endpoint_override', False): - # We need to set endpoint_override for OBS, since otherwise it - # fails dramatically + # SDK respects skip_discovery only if endpoint_override is set. + # In case, when append_project_id is skipped for the service, + # but the discovery on the service is not working - we might be + # failing dramatically. ep = conn.endpoint_for(sd.service_type) conn.config.config[ '_'.join([ @@ -293,6 +309,8 @@ def load(conn, **kwargs): # for some proxies to use them setattr(conn, 'get_ak_sk', get_ak_sk) + patch_openstack_resources() + return None From 69035abfddff7fa6464b9111e68edb64cb98919a Mon Sep 17 00:00:00 2001 From: Vineet Pruthi Date: Fri, 27 Mar 2020 05:56:56 +0000 Subject: [PATCH 60/73] Formatting Fixes and raise error if nat gateway not found --- otcextensions/osclient/nat/v2/dnat.py | 106 +++++++++++------- otcextensions/osclient/nat/v2/gateway.py | 130 +++++++++++++++-------- otcextensions/osclient/nat/v2/snat.py | 98 +++++++++++------ otcextensions/sdk/nat/v2/_proxy.py | 8 +- 4 files changed, 222 insertions(+), 120 deletions(-) diff --git a/otcextensions/osclient/nat/v2/dnat.py b/otcextensions/osclient/nat/v2/dnat.py index e41a8c7fa..84da45469 100644 --- a/otcextensions/osclient/nat/v2/dnat.py +++ b/otcextensions/osclient/nat/v2/dnat.py @@ -47,65 +47,88 @@ def get_parser(self, prog_name): parser.add_argument( '--id', metavar='', - help=_('Specifies the ID of the SNAT rule.')) + help=_("Specifies the ID of the SNAT rule."), + ) parser.add_argument( '--limit', metavar='', type=int, - help=_('Limit to fetch number of records.')) + help=_("Limit to fetch number of records."), + ) parser.add_argument( '--project-id', metavar='', - help=_('Specifies the project ID.')) + help=_("Specifies the project ID."), + ) parser.add_argument( '--nat-gateway-id', metavar='', - help=_('Specifies the NAT gateway ID.')) + help=_("Specifies the NAT gateway ID."), + ) parser.add_argument( '--port-id', metavar='', - help=_('Specifies the port ID of an ECS or a BMS.')) + help=_("Specifies the port ID of an ECS or a BMS."), + ) parser.add_argument( '--private-ip', metavar='', - help=_('Specifies the private IP address, for example, ' - 'the IP address of a Direct Connect connection.')) + help=_("Specifies the private IP address, for example, " + "the IP address of a Direct Connect connection."), + ) parser.add_argument( '--internal-service-port', metavar='', - help=_('Specifies port used by ECSs or BMSs toprovide ' - 'services for external systems.')) + help=_("Specifies port used by ECSs or BMSs to provide " + "services for external systems."), + ) parser.add_argument( '--floating-ip-id', metavar='', - help=_('Specifies the EIP ID.')) + help=_("Specifies the Floating IP ID."), + ) parser.add_argument( '--floating-ip-address', metavar='', - help=_('Specifies the EIP.')) + help=_("Specifies the Floating IP."), + ) parser.add_argument( '--external-service-port', metavar='', - help=_('Specifies the port for providing external services.')) + help=_("Specifies the port for providing external services."), + ) parser.add_argument( '--protocol', metavar='', - help=_('Specifies the protocol type.')) + help=_("Specifies the protocol type." + "Currently, TCP, UDP, and ANY are supported."), + ) parser.add_argument( '--status', metavar='', - help=_('Specifies the status of the DNAT rule.')) + help=_("Specifies the status of the DNAT rule." + "\nACTIVE: The resource status is normal." + "\nPENDING_CREATE: The resource is being created." + "\nPENDING_UPDATE: The resource is being updated." + "\nPENDING_DELETE: The resource is being deleted." + "\nEIP_FREEZED: The EIP of the resource is frozen." + "\nINACTIVE: The resource status is abnormal."), + ) parser.add_argument( '--admin-state-up', metavar='', - help=_('Specifies whether the DNAT rule is enabled or disabled.')) + help=_("Specifies whether the DNAT rule is enabled or " + "disabled. The value can be:" + "\ntrue: The DNAT rule is enabled." + "\nfalse: The DNAT rule is disabled."), + ) parser.add_argument( '--created-at', metavar='', - help=_('Specifies when the DNAT rule is created (UTC time). ' - 'Its valuerounds to 6 decimal places forseconds. ' - 'The format is yyyy-mm-ddhh:mm:ss.')) - + help=_("Specifies when the DNAT rule is created (UTC time). " + "Its value rounds to 6 decimal places forseconds. " + "The format is yyyy-mm-ddhh:mm:ss."), + ) return parser def take_action(self, parsed_args): @@ -128,8 +151,9 @@ def take_action(self, parsed_args): ] attrs = {} for arg in args_list: - if getattr(parsed_args, arg): - attrs[arg] = getattr(parsed_args, arg) + val = getattr(parsed_args, arg) + if val: + attrs[arg] = val data = client.dnat_rules(**attrs) return ( @@ -149,7 +173,7 @@ def get_parser(self, prog_name): parser.add_argument( 'dnat', metavar='', - help=_('Specifies the ID of the SNAT Rule'), + help=_("Specifies the ID of the SNAT Rule"), ) return parser @@ -170,41 +194,47 @@ def get_parser(self, prog_name): parser = super(CreateDnatRule, self).get_parser(prog_name) parser.add_argument( '--nat-gateway-id', + metavar='', required=True, - metavar="", - help=_("Specifies the ID of the NAT gateway")) + help=_("Specifies the ID of the NAT Gateway."), + ) parser.add_argument( '--port-id', metavar='', - help=_('Specifies the port ID of an ECS or a BMS.')) + help=_("Specifies the port ID of an ECS or a BMS."), + ) parser.add_argument( '--private-ip', metavar='', - help=_('Specifies the private IP address, for example, ' - 'the IP address of a Direct Connect connection.')) + help=_("Specifies the private IP address, for example, " + "the IP address of a Direct Connect connection."), + ) parser.add_argument( '--internal-service-port', metavar='', required=True, - help=_('Specifies port used by ECSs or BMSs toprovide ' - 'services for external systems.')) + help=_("Specifies port used by ECSs or BMSs to provide " + "services for external systems."), + ) parser.add_argument( '--floating-ip-id', metavar="", required=True, - help=_('Specifies the EIP ID. Multiple EIPs are ' - 'separated using commas')) + help=_("Specifies the Floating IP ID. Multiple " + "Floating IPs are separated using commas."), + ) parser.add_argument( '--external-service-port', metavar='', required=True, - help=_('Specifies the port for providing external services.')) + help=_("Specifies the port for providing external services."), + ) parser.add_argument( '--protocol', metavar='', required=True, - help=_('Specifies the protocol type.')) - + help=_("Specifies the protocol type."), + ) return parser def take_action(self, parsed_args): @@ -221,8 +251,9 @@ def take_action(self, parsed_args): ] attrs = {} for arg in args_list: - if getattr(parsed_args, arg): - attrs[arg] = getattr(parsed_args, arg) + val = getattr(parsed_args, arg) + if val: + attrs[arg] = val obj = client.create_dnat_rule(**attrs) @@ -241,9 +272,8 @@ def get_parser(self, prog_name): parser.add_argument( 'dnat', metavar='', - help=_('Specifies the ID of the DNAT Rule'), + help=_("Specifies the ID of the DNAT Rule."), ) - return parser def take_action(self, parsed_args): diff --git a/otcextensions/osclient/nat/v2/gateway.py b/otcextensions/osclient/nat/v2/gateway.py index c402c162b..c0bed553c 100644 --- a/otcextensions/osclient/nat/v2/gateway.py +++ b/otcextensions/osclient/nat/v2/gateway.py @@ -39,48 +39,76 @@ def get_parser(self, prog_name): parser.add_argument( '--id', metavar='', - help=_('Specifies the ID of the NAT Gateway.')) + help=_("Specifies the ID of the NAT Gateway."), + ) parser.add_argument( '--limit', metavar='', type=int, - help=_('Limit to fetch number of records.')) + help=_("Limit to fetch number of records."), + ) parser.add_argument( '--project-id', metavar='', - help=_('Specifies the project ID.')) + help=_("Specifies the project ID."), + ) parser.add_argument( '--name', metavar='', - help=_('Specifies the Name of the NAT Gateway.')) + help=_("Specifies the Name of the NAT Gateway."), + ) parser.add_argument( '--spec', metavar='', - help=_('Specifies the type of the NAT Gateway.')) + help=_("Specifies the type of the NAT Gateway. " + "The value of spec can be:" + "\n1: small type, which supports up to 10,000 " + "SNAT connections." + "\n2: medium type, which supports up to 50,000 " + "SNAT connections." + "\n3: large type, which supports up to 200,000 " + "SNAT connections." + "\n4: extra-large type, which supports up to " + "1,000,000 SNAT connections."), + ) parser.add_argument( '--router-id', metavar='', - help=_('Specifies the router ID.')) + help=_("Specifies the router ID."), + ) parser.add_argument( '--internal-network-id', metavar='', - help=_('Specifies the network ID.')) + help=_("Specifies the network ID of the downstream " + "interface (the next hop of the DVR) of the " + "NAT Gateway."), + ) parser.add_argument( '--status', metavar='', - help=_('Specifies the status of the NAT Gateway.')) + help=_("Specifies the status of the NAT Gateway." + "\nACTIVE: The resource status is normal." + "\nPENDING_CREATE: The resource is being created." + "\nPENDING_UPDATE: The resource is being updated." + "\nPENDING_DELETE: The resource is being deleted." + "\nEIP_FREEZED: The EIP of the resource is frozen." + "\nINACTIVE: The resource status is abnormal."), + ) parser.add_argument( '--admin-state-up', metavar='', - help=_('Specifies whether the NAT Gateway is enabled ' - 'or disabled.')) + help=_("Specifies whether the NAT Gateway is enabled " + "or disabled. The value can be:" + "\ntrue: The NAT gateway is up." + "\nfalse: The NAT gateway is down."), + ) parser.add_argument( '--created-at', metavar='', - help=_('Specifies when the NAT Gateway is created (UTC time). ' - 'Its valuerounds to 6 decimal places forseconds. ' - 'The format is yyyy-mm-ddhh:mm:ss.')) - + help=_("Specifies when the NAT Gateway is created (UTC time). " + "Its valuerounds to 6 decimal places forseconds. " + "The format is yyyy-mm-ddhh:mm:ss."), + ) return parser def take_action(self, parsed_args): @@ -98,8 +126,9 @@ def take_action(self, parsed_args): 'created_at'] attrs = {} for arg in args_list: - if getattr(parsed_args, arg): - attrs[arg] = getattr(parsed_args, arg) + val = getattr(parsed_args, arg) + if val: + attrs[arg] = val data = client.gateways(**attrs) @@ -115,14 +144,13 @@ def get_parser(self, prog_name): parser.add_argument( 'gateway', metavar='', - help=_('Specifies the ID of the NAT Gateway.'), + help=_("Specifies the Name or ID of the NAT Gateway."), ) return parser def take_action(self, parsed_args): client = self.app.client_manager.nat obj = client.find_gateway(parsed_args.gateway) - display_columns, columns = _get_columns(obj) data = utils.get_item_properties(obj, columns) @@ -136,35 +164,44 @@ def get_parser(self, prog_name): parser = super(CreateNatGateway, self).get_parser(prog_name) parser.add_argument( 'name', - metavar="", - help=_("Specifies the name of the NAT Gateway.")) + metavar='', + help=_("Specifies the name of the NAT Gateway."), + ) parser.add_argument( '--description', - metavar="", - help=_("Provides supplementary informationabout the NAT gateway.")) + metavar='', + help=_("Provides supplementary information about " + "the NAT Gateway."), + ) parser.add_argument( '--spec', - metavar="", + metavar='', required=True, help=_( - "Specifies the type of the NAT gateway." + "Specifies the type of the NAT Gateway. " + "The value can be:" "\n1: small type, which supports up to 10,000 " - "SNAT connections.\n2: medium type, which supports " - "up to 50,000 SNAT connections.\n3: large type, which " - "supports up to 200,000 SNAT connections.\n4: extra-large " - "type, which supports up to 1,000,000 SNAT connections.")) + "SNAT connections." + "\n2: medium type, which supports up to 50,000 " + "SNAT connections." + "\n3: large type, which supports up to 200,000 " + "SNAT connections." + "\n4: extra-large type, which supports up to " + "1,000,000 SNAT connections."), + ) parser.add_argument( '--router-id', - metavar="", + metavar='', required=True, - help=_("Specifies the VPC ID")) + help=_("Specifies the VPC ID."), + ) parser.add_argument( '--internal-network-id', - metavar="", + metavar='', required=True, - help=_("Specifies the network ID of thedownstream interface " - "(the next hop ofthe DVR) of the NAT gateway.")) - + help=_("Specifies the network ID of the downstream interface " + "(the next hop of the DVR) of the NAT Gateway."), + ) return parser def take_action(self, parsed_args): @@ -178,8 +215,9 @@ def take_action(self, parsed_args): 'internal_network_id'] attrs = {} for arg in args_list: - if getattr(parsed_args, arg): - attrs[arg] = getattr(parsed_args, arg) + val = getattr(parsed_args, arg) + if val: + attrs[arg] = val obj = client.create_gateway(**attrs) @@ -197,20 +235,23 @@ def get_parser(self, prog_name): parser.add_argument( 'gateway', metavar='', - help=_('Specifies the Name or ID of the NAT Gateway.'), + help=_("Specifies the Name or ID of the NAT Gateway."), ) parser.add_argument( '--name', - metavar="", - help=_("Specifies the name of the NAT Gateway.")) + metavar='', + help=_("Specifies the name of the NAT Gateway."), + ) parser.add_argument( '--description', - metavar="", - help=_("Provides supplementary informationabout the NAT gateway.")) + metavar='', + help=_("Provides supplementary informationabout the NAT gateway."), + ) parser.add_argument( '--spec', - metavar="", - help=_("Specifies the type of the NAT gateway.")) + metavar='', + help=_("Specifies the type of the NAT Gateway."), + ) return parser def take_action(self, parsed_args): @@ -241,9 +282,8 @@ def get_parser(self, prog_name): parser.add_argument( 'gateway', metavar='', - help=_('Specifies the Name or ID of the NAT gateway.'), + help=_("Specifies the Name or ID of the NAT Gateway."), ) - return parser def take_action(self, parsed_args): diff --git a/otcextensions/osclient/nat/v2/snat.py b/otcextensions/osclient/nat/v2/snat.py index b22ef7293..edcd1b1a5 100644 --- a/otcextensions/osclient/nat/v2/snat.py +++ b/otcextensions/osclient/nat/v2/snat.py @@ -46,56 +46,76 @@ def get_parser(self, prog_name): parser.add_argument( '--id', metavar='', - help=_('Specifies the ID of the SNAT rule.')) + help=_("Specifies the ID of the SNAT rule."), + ) parser.add_argument( '--limit', metavar='', type=int, - help=_('Limit to fetch number of records.')) + help=_("Limit to fetch number of records."), + ) parser.add_argument( '--project-id', metavar='', - help=_('Specifies the project ID.')) + help=_("Specifies the project ID."), + ) parser.add_argument( '--nat-gateway-id', metavar='', - help=_('Specifies the NAT gateway ID.')) + help=_("Specifies the NAT gateway ID."), + ) parser.add_argument( '--network-id', metavar='', - help=_('Specifies the network ID used by theSNAT rule.')) + help=_("Specifies the network ID used by the SNAT rule."), + ) parser.add_argument( '--cidr', metavar='', - help=_('Specifies a subset of the VPC subnetCIDR block or ' - 'a CIDR block of DirectConnect connection.')) + help=_("Specifies a subset of the VPC subnet CIDR block or " + "a CIDR block of Direct Connect connection."), + ) parser.add_argument( '--source-type', metavar='', - help=_('Specifies Source Type.')) + help=_("Specifies Source Type."), + ) parser.add_argument( '--floating-ip-id', metavar='', - help=_('Specifies the EIP ID.')) + help=_("Specifies the Floating IP ID."), + ) parser.add_argument( '--floating-ip-address', metavar='', - help=_('Specifies the EIP.')) + help=_("Specifies the Floating IP."), + ) parser.add_argument( '--status', metavar='', - help=_('Specifies the status of the SNATrule.')) + help=_("Specifies the status of the SNAT rule." + "\nACTIVE: The resource status is normal." + "\nPENDING_CREATE: The resource is being created." + "\nPENDING_UPDATE: The resource is being updated." + "\nPENDING_DELETE: The resource is being deleted." + "\nEIP_FREEZED: The EIP of the resource is frozen." + "\nINACTIVE: The resource status is abnormal."), + ) parser.add_argument( '--admin-state-up', metavar='', - help=_('Specifies whether the SNAT rule isenabled or disabled.')) + help=_("Specifies whether the SNAT rule is enabled or " + "disabled. The value can be:" + "\ntrue: The SNAT rule is enabled." + "\nfalse: The SNAT rule is disabled."), + ) parser.add_argument( '--created-at', metavar='', - help=_('Specifies when the SNAT rule iscreated (UTC time). ' - 'Its valuerounds to 6 decimal places forseconds. ' - 'The format is yyyy-mm-ddhh:mm:ss.')) - + help=_("Specifies when the SNAT rule is created (UTC time). " + "Its value rounds to 6 decimal places for seconds. " + "The format is yyyy-mm-ddhh:mm:ss."), + ) return parser def take_action(self, parsed_args): @@ -116,8 +136,9 @@ def take_action(self, parsed_args): 'created_at'] attrs = {} for arg in args_list: - if getattr(parsed_args, arg): - attrs[arg] = getattr(parsed_args, arg) + val = getattr(parsed_args, arg) + if val: + attrs[arg] = val data = client.snat_rules(**attrs) @@ -138,7 +159,7 @@ def get_parser(self, prog_name): parser.add_argument( 'snat', metavar='', - help=_('Specifies the ID of the SNAT Rule'), + help=_("Specifies the ID of the SNAT Rule."), ) return parser @@ -161,33 +182,39 @@ def get_parser(self, prog_name): '--nat-gateway-id', required=True, metavar='', - help=_('Specifies the ID of the NAT gateway')) + help=_("Specifies the ID of the NAT gateway."), + ) parser.add_argument( '--floating-ip-id', metavar='', required=True, - help=_('Specifies the EIP ID. Multiple EIPs ' - 'are separated using commas')) + help=_("Specifies the Floating IP ID. Multiple " + "Floating IPs are separated using commas."), + ) parser.add_argument( '--network-id', metavar='', - help=_('Specifies the network ID used by the SNAT rule. ' - 'This parameter and cidr arealternative.')) + help=_("Specifies the network ID used by the SNAT rule. " + "This parameter and cidr are alternative."), + ) parser.add_argument( '--cidr', metavar='', - help=_('Specifies CIDR, which can be in the formatof a ' - 'network segment or a host IP address')) + help=_("Specifies CIDR, which can be in the format of a " + "network segment or a host IP address."), + ) parser.add_argument( '--source-type', metavar='', help=_( - 'Specifies the source type.\n0: Either network_id ' - 'or cidr can be specified in a VPC.\n1: Only cidr ' - 'can be specified over a Direct Connect connection.' - '\nIf no value is entered, the default value 0 (VPC) ' - 'is used.')) - + "Specifies the source type." + "\n0: Either network_id or cidr can be " + "specified in a VPC." + "\n1: Only cidr can be specified over a " + "Direct Connect connection." + "\nIf no value is entered, the default " + "value 0 (VPC) is used."), + ) return parser def take_action(self, parsed_args): @@ -202,8 +229,9 @@ def take_action(self, parsed_args): ] attrs = {} for arg in args_list: - if getattr(parsed_args, arg): - attrs[arg] = getattr(parsed_args, arg) + val = getattr(parsed_args, arg) + if val: + attrs[arg] = val obj = client.create_snat_rule(**attrs) @@ -222,7 +250,7 @@ def get_parser(self, prog_name): parser.add_argument( 'snat', metavar='', - help=_('Specifies the ID of the SNAT Rule'), + help=_("Specifies the ID of the SNAT Rule."), ) return parser diff --git a/otcextensions/sdk/nat/v2/_proxy.py b/otcextensions/sdk/nat/v2/_proxy.py index bde70a21a..23b508e9e 100644 --- a/otcextensions/sdk/nat/v2/_proxy.py +++ b/otcextensions/sdk/nat/v2/_proxy.py @@ -95,8 +95,12 @@ def find_gateway(self, name_or_id, ignore_missing=True): :returns: ``None`` """ - return self._find(_gateway.Gateway, name_or_id, - ignore_missing=ignore_missing) + obj = self._find(_gateway.Gateway, name_or_id) + if obj is None: + raise RuntimeError( + 'The provide NAT Gateway id/name={} ' + 'could not be found'.format(name_or_id)) + return obj # ======== SNAT rules ======== def create_snat_rule(self, **attrs): From 2fbadeab9d17921be1dfbcc9014463fcbb99d049 Mon Sep 17 00:00:00 2001 From: Vineet Pruthi Date: Mon, 30 Mar 2020 07:50:17 +0000 Subject: [PATCH 61/73] Fixed osclient Unit Tests for nat --- .../tests/unit/osclient/nat/v2/fakes.py | 54 +++++++-- .../tests/unit/osclient/nat/v2/test_dnat.py | 74 ++++++++++-- .../unit/osclient/nat/v2/test_gateway.py | 108 +++++++++++++++--- .../tests/unit/osclient/nat/v2/test_snat.py | 65 +++++++++-- 4 files changed, 256 insertions(+), 45 deletions(-) diff --git a/otcextensions/tests/unit/osclient/nat/v2/fakes.py b/otcextensions/tests/unit/osclient/nat/v2/fakes.py index d746af427..be7eaba25 100644 --- a/otcextensions/tests/unit/osclient/nat/v2/fakes.py +++ b/otcextensions/tests/unit/osclient/nat/v2/fakes.py @@ -11,7 +11,7 @@ # under the License. # import uuid -import time +from datetime import datetime import mock @@ -44,10 +44,6 @@ def setUp(self): self.client = self.app.client_manager.nat - self.nat_gateway_mock = FakeNatGateway - self.snat_rule_mock = FakeSnatRule - self.dnat_rule_mock = FakeDnatRule - class FakeNatGateway(test_base.Fake): """Fake one or more datastore versions.""" @@ -67,13 +63,27 @@ def generate(cls): "description": "my nat gateway", "admin_state_up": 'true', "tenant_id": "tenant-id-" + uuid.uuid4().hex, - "created_at": time.clock() * 1000, + "created_at": datetime.now().strftime("%Y-%m-%d %H:%M:%s")[:-4], "spec": "1", "internal_network_id": "net-id-" + uuid.uuid4().hex } return gateway.Gateway(**object_info) + @staticmethod + def find_gateway(nat_gateway, name_or_id): + """Get a Mock object with faked dnat_rule. + :param dnat_rule: + A FakeResource objects faking dnat_rule + :return: + A Mock object with side_effect set to a faked + dnat_rule + """ + if name_or_id in [nat_gateway.id, nat_gateway.name]: + return mock.Mock(return_value=nat_gateway) + else: + return mock.Mock(side_effect=RuntimeError('404 Not Found')) + class FakeSnatRule(test_base.Fake): """Fake one or more Instance.""" @@ -96,12 +106,26 @@ def generate(cls): "cidr": uuid.uuid4().hex, "source_type": 0, "tenant_id": "tenant-id-" + uuid.uuid4().hex, - "created_at": time.clock() * 1000, + "created_at": datetime.now().strftime("%Y-%m-%d %H:%M:%s")[:-4], "floating_ip_address": uuid.uuid4().hex } return snat.Snat.existing(**object_info) + @staticmethod + def get_snat_rule(snat_rule, snat_rule_id): + """Get a Mock object with faked dnat_rule. + :param dnat_rule: + A FakeResource objects faking dnat_rule + :return: + A Mock object with side_effect set to a faked + dnat_rule + """ + if snat_rule.id == snat_rule_id: + return mock.Mock(return_value=snat_rule) + else: + return mock.Mock(side_effect=RuntimeError('404 Not Found')) + class FakeDnatRule(test_base.Fake): """Fake one or more Backup""" @@ -118,10 +142,24 @@ def generate(cls): "protocol": "any", "tenant_id": "abc", "port_id": "", - "created_at": time.clock() * 1000, + "created_at": datetime.now().strftime("%Y-%m-%d %H:%M:%s")[:-4], "floating_ip_address": uuid.uuid4().hex, "external_service_port": 0 } obj = dnat.Dnat.existing(**object_info) return obj + + @staticmethod + def get_dnat_rule(dnat_rule, dnat_rule_id): + """Get a Mock object with faked dnat_rule. + :param dnat_rule: + A FakeResource objects faking dnat_rule + :return: + A Mock object with side_effect set to a faked + dnat_rule + """ + if dnat_rule.id == dnat_rule_id: + return mock.Mock(return_value=dnat_rule) + else: + return mock.Mock(side_effect=RuntimeError('404 Not Found')) diff --git a/otcextensions/tests/unit/osclient/nat/v2/test_dnat.py b/otcextensions/tests/unit/osclient/nat/v2/test_dnat.py index 7ef4a7abc..99ee0f5c2 100644 --- a/otcextensions/tests/unit/osclient/nat/v2/test_dnat.py +++ b/otcextensions/tests/unit/osclient/nat/v2/test_dnat.py @@ -162,15 +162,16 @@ def setUp(self): self.cmd = dnat.ShowDnatRule(self.app, None) - self.client.get_dnat_rule = mock.Mock(return_value=self._data) + self.client.get_dnat_rule = ( + fakes.FakeDnatRule.get_dnat_rule(self._data, self._data.id)) def test_show(self): arglist = [ - 'test_dnat_rule_id', + self._data.id, ] verifylist = [ - ('dnat', 'test_dnat_rule_id'), + ('dnat', self._data.id), ] # Verify cm is triggered with default parameters @@ -178,11 +179,35 @@ def test_show(self): # Trigger the action columns, data = self.cmd.take_action(parsed_args) - self.client.get_dnat_rule.assert_called_with('test_dnat_rule_id') + self.client.get_dnat_rule.assert_called_with(self._data.id) self.assertEqual(self.columns, columns) self.assertEqual(self.data, data) + def test_show_non_existent(self): + arglist = [ + 'unexist_dnat_rule_id', + ] + + verifylist = [ + ('dnat', 'unexist_dnat_rule_id'), + ] + + # Verify cm is triggered with default parameters + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + self.client.get_dnat_rule = ( + fakes.FakeDnatRule.get_dnat_rule( + self._data, 'unexist_dnat_rule_id')) + + # Trigger the action + try: + self.cmd.take_action(parsed_args) + self.fail('CommandError should be raised.') + except Exception as e: + self.assertEqual('404 Not Found', str(e)) + self.client.get_dnat_rule.assert_called_with('unexist_dnat_rule_id') + class TestCreateDnatRule(fakes.TestNat): @@ -251,23 +276,24 @@ def test_create(self): class TestDeleteDnatRule(fakes.TestNat): - data = fakes.FakeDnatRule.create_one() + _data = fakes.FakeDnatRule.create_one() def setUp(self): super(TestDeleteDnatRule, self).setUp() - self.cmd = dnat.DeleteDnatRule(self.app, None) + self.client.get_dnat_rule = ( + fakes.FakeDnatRule.get_dnat_rule(self._data, self._data.id)) + self.client.delete_dnat_rule = mock.Mock(return_value=None) - self.client.get_dnat_rule = mock.Mock(return_value=self.data) - self.client.delete_dnat_rule = mock.Mock(return_value=self.data) + self.cmd = dnat.DeleteDnatRule(self.app, None) def test_delete(self): arglist = [ - 'test_dnat_rule_id', + self._data.id, ] verifylist = [ - ('dnat', 'test_dnat_rule_id'), + ('dnat', self._data.id), ] # Verify cm is triggered with default parameters @@ -276,6 +302,30 @@ def test_delete(self): # Trigger the action self.cmd.take_action(parsed_args) - self.client.get_dnat_rule.assert_called_with('test_dnat_rule_id') + self.client.get_dnat_rule.assert_called_with(self._data.id) + + self.client.delete_dnat_rule.assert_called_with(self._data.id) - self.client.delete_dnat_rule.assert_called_with(self.data.id) + def test_delete_non_existent(self): + arglist = [ + 'unexist_dnat_rule_id', + ] + + verifylist = [ + ('dnat', 'unexist_dnat_rule_id'), + ] + + # Verify cm is triggered with default parameters + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + self.client.get_dnat_rule = ( + fakes.FakeDnatRule.get_dnat_rule( + self._data, 'unexist_dnat_rule_id')) + + # Trigger the action + try: + self.cmd.take_action(parsed_args) + self.fail('CommandError should be raised.') + except Exception as e: + self.assertEqual('404 Not Found', str(e)) + self.client.get_dnat_rule.assert_called_with('unexist_dnat_rule_id') diff --git a/otcextensions/tests/unit/osclient/nat/v2/test_gateway.py b/otcextensions/tests/unit/osclient/nat/v2/test_gateway.py index dd8dbd52b..cc1f054c2 100644 --- a/otcextensions/tests/unit/osclient/nat/v2/test_gateway.py +++ b/otcextensions/tests/unit/osclient/nat/v2/test_gateway.py @@ -185,18 +185,17 @@ def setUp(self): self.cmd = gateway.UpdateNatGateway(self.app, None) - self.client.find_gateway = mock.Mock(return_value=self._data) self.client.update_gateway = mock.Mock(return_value=self._data) def test_update(self): arglist = [ - 'test-gateway', + self._data.name, '--name', 'test-gateway-updated', '--description', 'nat gateway updated', '--spec', '2', ] verifylist = [ - ('gateway', 'test-gateway'), + ('gateway', self._data.name), ('name', 'test-gateway-updated'), ('description', 'nat gateway updated'), ('spec', '2'), @@ -204,10 +203,13 @@ def test_update(self): # Verify cm is triggereg with default parameters parsed_args = self.check_parser(self.cmd, arglist, verifylist) + self.client.find_gateway = ( + fakes.FakeNatGateway.find_gateway(self._data, self._data.name)) + # Trigger the action columns, data = self.cmd.take_action(parsed_args) - self.client.find_gateway.assert_called_with('test-gateway') + self.client.find_gateway.assert_called_with(self._data.name) self.client.update_gateway.assert_called_with( self._data.id, name='test-gateway-updated', @@ -241,55 +243,127 @@ def setUp(self): self.cmd = gateway.ShowNatGateway(self.app, None) - self.client.find_gateway = mock.Mock(return_value=self._data) - def test_show(self): arglist = [ - 'test_gateway', + self._data.id, ] verifylist = [ - ('gateway', 'test_gateway'), + ('gateway', self._data.id), ] # Verify cm is triggered with default parameters parsed_args = self.check_parser(self.cmd, arglist, verifylist) + self.client.find_gateway = ( + fakes.FakeNatGateway.find_gateway(self._data, self._data.id)) + # Trigger the action columns, data = self.cmd.take_action(parsed_args) - self.client.find_gateway.assert_called_with('test_gateway') + self.client.find_gateway.assert_called_with(self._data.id) self.assertEqual(self.columns, columns) self.assertEqual(self.data, data) + def test_show_non_existent(self): + arglist = [ + 'unexist_nat_gateway', + ] + + verifylist = [ + ('gateway', 'unexist_nat_gateway'), + ] + + # Verify cm is triggered with default parameters + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + self.client.find_gateway = ( + fakes.FakeNatGateway.find_gateway( + self._data, 'unexist_nat_gateway')) + + # Trigger the action + try: + self.cmd.take_action(parsed_args) + self.fail('CommandError should be raised.') + except Exception as e: + self.assertEqual('404 Not Found', str(e)) + self.client.find_gateway.assert_called_with('unexist_nat_gateway') + class TestDeleteNatGateway(fakes.TestNat): - data = fakes.FakeNatGateway.create_one() + _data = fakes.FakeNatGateway.create_one() def setUp(self): super(TestDeleteNatGateway, self).setUp() self.cmd = gateway.DeleteNatGateway(self.app, None) - self.client.find_gateway = mock.Mock(return_value=self.data) - self.client.delete_gateway = mock.Mock(return_value=self.data) + self.client.find_gateway = ( + fakes.FakeNatGateway.find_gateway(self._data, self._data.id)) + self.client.delete_gateway = mock.Mock(return_value=None) + + def test_delete_by_id(self): + arglist = [ + self._data.id, + ] + + verifylist = [ + ('gateway', self._data.id), + ] + + # Verify cm is triggered with default parameters + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + # Trigger the action + self.cmd.take_action(parsed_args) + + self.client.find_gateway.assert_called_with(self._data.id) - def test_delete(self): + self.client.delete_gateway.assert_called_with(self._data.id) + + def test_delete_by_name(self): arglist = [ - 'test_gateway', + self._data.name, ] verifylist = [ - ('gateway', 'test_gateway'), + ('gateway', self._data.name), ] # Verify cm is triggered with default parameters parsed_args = self.check_parser(self.cmd, arglist, verifylist) + self.client.find_gateway = ( + fakes.FakeNatGateway.find_gateway(self._data, self._data.name)) + # Trigger the action self.cmd.take_action(parsed_args) - self.client.find_gateway.assert_called_with('test_gateway') + self.client.find_gateway.assert_called_with(self._data.name) + + self.client.delete_gateway.assert_called_with(self._data.id) - self.client.delete_gateway.assert_called_with(self.data.id) + def test_delete_non_existent(self): + arglist = [ + 'unexist_nat_gateway', + ] + + verifylist = [ + ('gateway', 'unexist_nat_gateway'), + ] + + # Verify cm is triggered with default parameters + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + self.client.find_gateway = ( + fakes.FakeNatGateway.find_gateway( + self._data, 'unexist_nat_gateway')) + + # Trigger the action + try: + self.cmd.take_action(parsed_args) + self.fail('CommandError should be raised.') + except Exception as e: + self.assertEqual('404 Not Found', str(e)) + self.client.find_gateway.assert_called_with('unexist_nat_gateway') diff --git a/otcextensions/tests/unit/osclient/nat/v2/test_snat.py b/otcextensions/tests/unit/osclient/nat/v2/test_snat.py index fba0db940..23c861630 100644 --- a/otcextensions/tests/unit/osclient/nat/v2/test_snat.py +++ b/otcextensions/tests/unit/osclient/nat/v2/test_snat.py @@ -232,26 +232,51 @@ def test_show(self): self.assertEqual(self.columns, columns) self.assertEqual(self.data, data) + def test_show_non_existent(self): + arglist = [ + 'unexist_snat_rule_id', + ] + + verifylist = [ + ('snat', 'unexist_snat_rule_id'), + ] + + # Verify cm is triggered with default parameters + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + self.client.get_snat_rule = ( + fakes.FakeSnatRule.get_snat_rule( + self._data, 'unexist_snat_rule_id')) + + # Trigger the action + try: + self.cmd.take_action(parsed_args) + self.fail('CommandError should be raised.') + except Exception as e: + self.assertEqual('404 Not Found', str(e)) + self.client.get_snat_rule.assert_called_with('unexist_snat_rule_id') + class TestDeleteSnatRule(fakes.TestNat): - data = fakes.FakeSnatRule.create_one() + _data = fakes.FakeSnatRule.create_one() def setUp(self): super(TestDeleteSnatRule, self).setUp() - self.cmd = snat.DeleteSnatRule(self.app, None) + self.client.get_snat_rule = ( + fakes.FakeSnatRule.get_snat_rule(self._data, self._data.id)) + self.client.delete_snat_rule = mock.Mock(return_value=None) - self.client.get_snat_rule = mock.Mock(return_value=self.data) - self.client.delete_snat_rule = mock.Mock(return_value=self.data) + self.cmd = snat.DeleteSnatRule(self.app, None) def test_delete(self): arglist = [ - 'test_snat_rule_id', + self._data.id, ] verifylist = [ - ('snat', 'test_snat_rule_id'), + ('snat', self._data.id), ] # Verify cm is triggered with default parameters @@ -260,6 +285,30 @@ def test_delete(self): # Trigger the action self.cmd.take_action(parsed_args) - self.client.get_snat_rule.assert_called_with('test_snat_rule_id') + self.client.get_snat_rule.assert_called_with(self._data.id) + + self.client.delete_snat_rule.assert_called_with(self._data.id) - self.client.delete_snat_rule.assert_called_with(self.data.id) + def test_delete_non_existent(self): + arglist = [ + 'unexist_snat_rule_id', + ] + + verifylist = [ + ('snat', 'unexist_snat_rule_id'), + ] + + # Verify cm is triggered with default parameters + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + self.client.get_snat_rule = ( + fakes.FakeSnatRule.get_snat_rule( + self._data, 'unexist_snat_rule_id')) + + # Trigger the action + try: + self.cmd.take_action(parsed_args) + self.fail('CommandError should be raised.') + except Exception as e: + self.assertEqual('404 Not Found', str(e)) + self.client.get_snat_rule.assert_called_with('unexist_snat_rule_id') From 79312cbac3208294e84a63221b97be639ec4d55d Mon Sep 17 00:00:00 2001 From: Vineet Pruthi Date: Mon, 30 Mar 2020 10:05:25 +0000 Subject: [PATCH 62/73] Fixed docstring for nat fakes.py --- .../tests/unit/osclient/nat/v2/fakes.py | 33 ++++++++++++------- 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/otcextensions/tests/unit/osclient/nat/v2/fakes.py b/otcextensions/tests/unit/osclient/nat/v2/fakes.py index be7eaba25..b79f0c48d 100644 --- a/otcextensions/tests/unit/osclient/nat/v2/fakes.py +++ b/otcextensions/tests/unit/osclient/nat/v2/fakes.py @@ -72,12 +72,15 @@ def generate(cls): @staticmethod def find_gateway(nat_gateway, name_or_id): - """Get a Mock object with faked dnat_rule. - :param dnat_rule: - A FakeResource objects faking dnat_rule + """Get a Mock object with faked nat_gateway. + :param nat_gateway: + A FakeResource objects faking nat_gateway + :param name_or_id: + name or id of nat_gateway :return: - A Mock object with side_effect set to a faked - dnat_rule + A Mock object with faked nat_gateway or + side_effect=RuntimeError if name or id + doesnt matches in faked nat_gateway """ if name_or_id in [nat_gateway.id, nat_gateway.name]: return mock.Mock(return_value=nat_gateway) @@ -114,12 +117,15 @@ def generate(cls): @staticmethod def get_snat_rule(snat_rule, snat_rule_id): - """Get a Mock object with faked dnat_rule. - :param dnat_rule: - A FakeResource objects faking dnat_rule + """Get a Mock object with faked snat_rule. + :param snat_rule: + A FakeResource objects faking snat_rule + :param snat_rule_id: + Id of snat_rule :return: - A Mock object with side_effect set to a faked - dnat_rule + A Mock object with faked snat_rule or + side_effect=RuntimeError if snat_rule_id + doesnt matches in faked snat_rule Id """ if snat_rule.id == snat_rule_id: return mock.Mock(return_value=snat_rule) @@ -155,9 +161,12 @@ def get_dnat_rule(dnat_rule, dnat_rule_id): """Get a Mock object with faked dnat_rule. :param dnat_rule: A FakeResource objects faking dnat_rule + :param dnat_rule_id: + Id of dnat_rule :return: - A Mock object with side_effect set to a faked - dnat_rule + A Mock object with faked snat_rule or + side_effect=RuntimeError if dnat_rule_id + doesnt matches in faked dnat_rule Id """ if dnat_rule.id == dnat_rule_id: return mock.Mock(return_value=dnat_rule) From aa7c5bc993d244a9b0517f29281eb298ab3c2a6f Mon Sep 17 00:00:00 2001 From: Vineet Pruthi Date: Thu, 2 Apr 2020 06:53:35 +0000 Subject: [PATCH 63/73] Updated osclient functional tests for nat --- .../functional/osclient/nat/v2/common.py | 160 +++++++++++++++ .../osclient/nat/v2/test_dnat_rule.py | 175 +++------------- .../osclient/nat/v2/test_nat_gateway.py | 170 +++++----------- .../osclient/nat/v2/test_snat_rule.py | 187 +++--------------- 4 files changed, 258 insertions(+), 434 deletions(-) create mode 100644 otcextensions/tests/functional/osclient/nat/v2/common.py diff --git a/otcextensions/tests/functional/osclient/nat/v2/common.py b/otcextensions/tests/functional/osclient/nat/v2/common.py new file mode 100644 index 000000000..3669b3925 --- /dev/null +++ b/otcextensions/tests/functional/osclient/nat/v2/common.py @@ -0,0 +1,160 @@ +# 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 json +import uuid + +from openstackclient.tests.functional import base + + +class NatTestCase(base.TestCase): + """Common functional test bits for NAT commands""" + + UUID = uuid.uuid4().hex[:8] + ROUTER_NAME = 'sdk-test-router-' + UUID + NETWORK_NAME = 'sdk-test-net-' + UUID + SUBNET_NAME = 'sdk-test-subnet-' + UUID + + def setUp(self): + super(NatTestCase, self).setUp() + self.ROUTER_ID = None + self.NETWORK_ID = None + self.FLOATING_IP_ID = None + self.NAT_ID = None + self.SNAT_RULE_ID = None + self.DNAT_RULE_ID = None + + def create_nat_gateway(self, name=None): + self._initialize_network() + name = name or uuid.uuid4().hex + json_output = json.loads(self.openstack( + 'nat gateway create {name}' + ' --router-id {router_id}' + ' --internal-network-id {net_id}' + ' --spec {spec} -f json'.format( + name=name, + router_id=self.ROUTER_ID, + net_id=self.NETWORK_ID, + description='OTCE Lib Test', + spec=1) + )) + self.assertIsNotNone(json_output) + self.NAT_ID = json_output['id'] + return json_output + + def delete_nat_gateway(self): + self.addCleanup(self._denitialize_network) + self.openstack('nat gateway delete ' + self.NAT_ID) + + def create_snat_rule(self): + nat_gateway = self.create_nat_gateway() + self.assertIsNotNone(nat_gateway) + self.assertIsNotNone(self.FLOATING_IP_ID) + json_output = json.loads(self.openstack( + 'nat snat rule create ' + '--nat-gateway-id {nat_gateway_id} ' + '--floating-ip-id {floating_ip_id} ' + '--network-id {net_id} -f json'.format( + nat_gateway_id=nat_gateway['id'], + floating_ip_id=self.FLOATING_IP_ID, + net_id=self.NETWORK_ID) + )) + self.assertIsNotNone(json_output) + self.SNAT_RULE_ID = json_output['id'] + return json_output + + def delete_snat_rule(self): + self.addCleanup(self.delete_nat_gateway) + self.openstack( + 'nat snat rule delete ' + self.SNAT_RULE_ID) + + def create_dnat_rule(self): + nat_gateway = self.create_nat_gateway() + self.assertIsNotNone(nat_gateway) + self.assertIsNotNone(self.FLOATING_IP_ID) + json_output = json.loads(self.openstack( + 'nat dnat rule create ' + '--nat-gateway-id {nat_gateway_id} ' + '--floating-ip-id {floating_ip_id} ' + '--protocol {protocol} ' + '--internal-service-port 80 ' + '--external-service-port 80 ' + '--private-ip {private_ip} ' + '-f json'.format( + nat_gateway_id=nat_gateway['id'], + protocol='TCP', + private_ip='192.168.0.3', + floating_ip_id=self.FLOATING_IP_ID) + )) + self.assertIsNotNone(json_output) + self.DNAT_RULE_ID = json_output['id'] + return json_output + + def delete_dnat_rule(self): + self.addCleanup(self.delete_nat_gateway) + self.openstack( + 'nat dnat rule delete ' + self.DNAT_RULE_ID) + + def _initialize_network(self): + router = json.loads(self.openstack( + 'router create -f json ' + self.ROUTER_NAME + )) + net = json.loads(self.openstack( + 'network create -f json ' + self.NETWORK_NAME + )) + self.openstack( + 'subnet create {subnet} -f json ' + '--network {net} ' + '--subnet-range 192.168.0.0/24 '.format( + subnet=self.SUBNET_NAME, + net=self.NETWORK_NAME + )) + + self.openstack( + 'router add subnet {router} ' + '{subnet} '.format( + router=self.ROUTER_NAME, + subnet=self.SUBNET_NAME + ) + ) + + floating_ip = json.loads(self.openstack( + 'floating ip create -f json ' + '{network}'.format( + network='admin_external_net') + )) + + self.ROUTER_ID = router['id'] + self.NETWORK_ID = net['id'] + self.FLOATING_IP_ID = floating_ip['id'] + + def _denitialize_network(self): + self.openstack( + 'router remove subnet {router} ' + '{subnet} '.format( + router=self.ROUTER_NAME, + subnet=self.SUBNET_NAME + ) + ) + self.openstack( + 'subnet delete ' + self.SUBNET_NAME + ) + self.openstack( + 'network delete ' + self.NETWORK_NAME + ) + self.openstack( + 'router delete ' + self.ROUTER_NAME + ) + self.openstack( + 'floating ip delete ' + self.FLOATING_IP_ID + ) diff --git a/otcextensions/tests/functional/osclient/nat/v2/test_dnat_rule.py b/otcextensions/tests/functional/osclient/nat/v2/test_dnat_rule.py index 6dc7c1de4..d09b40084 100644 --- a/otcextensions/tests/functional/osclient/nat/v2/test_dnat_rule.py +++ b/otcextensions/tests/functional/osclient/nat/v2/test_dnat_rule.py @@ -11,36 +11,26 @@ # under the License. import json -import uuid -from openstackclient.tests.functional import base +from otcextensions.tests.functional.osclient.nat.v2 import common -class TestDnatRule(base.TestCase): +class TestDnatRule(common.NatTestCase): """Functional Tests for NAT Gateway""" - UUID = uuid.uuid4().hex[:8] - ROUTER_NAME = 'sdk-test-router-' + UUID - NETWORK_NAME = 'sdk-test-net-' + UUID - SUBNET_NAME = 'sdk-test-subnet-' + UUID - PORT_NAME = 'sdk-test-port-' + UUID - ROUTER_ID = None - NETWORK_ID = None - FLOATING_IP_ID = None - PORT_ID = None + @classmethod + def setUpClass(cls): + super(TestDnatRule, cls).setUpClass() - NAT_NAME = 'os-cli-test-' + UUID - NAT_ID = None - DNAT_RULE_ID = None - - def test_01_nat_dnat_rule_list(self): - self.openstack( + def test_nat_dnat_rule_list(self): + json_output = json.loads(self.openstack( 'nat dnat rule list -f json ' - ) + )) + self.assertIsNotNone(json_output) - def test_02_nat_dnat_rule_list_filters(self): - self.openstack( - 'nat dnat rule list ' + def test_nat_dnat_rule_list_filters(self): + json_output = json.loads(self.openstack( + 'nat dnat rule list -f json ' '--limit 1 --id 2 ' '--project-id 3 ' '--port-id 4 ' @@ -53,147 +43,38 @@ def test_02_nat_dnat_rule_list_filters(self): '--nat-gateway-id 11 ' '--protocol tcp ' '--admin-state-up true ' - ) - - def test_03_nat_dnat_rule_create(self): - self._create_nat_gateway() - self.assertIsNotNone(self.PORT_ID) - self.assertIsNotNone(self.FLOATING_IP_ID) - json_output = json.loads(self.openstack( - 'nat dnat rule create ' - '--nat-gateway-id {nat_gateway_id} ' - '--floating-ip-id {floating_ip_id} ' - '--protocol {protocol} ' - '--internal-service-port 80 ' - '--external-service-port 80 ' - '--private-ip {private_ip} ' - '-f json'.format( - nat_gateway_id=self.NAT_ID, - protocol='TCP', - private_ip='192.168.0.3', - floating_ip_id=self.FLOATING_IP_ID) )) self.assertIsNotNone(json_output) - TestDnatRule.DNAT_RULE_ID = json_output['id'] - def test_04_nat_dnat_rule_list_by_id(self): - self.assertIsNotNone(self.DNAT_RULE_ID) + def test_nat_dnat_rule_create(self): + json_output = self.create_dnat_rule() + self.addCleanup(self.delete_dnat_rule) + dnat_rule_id = json_output['id'] + nat_id = json_output['nat_gateway_id'] + + # List Dnat Rules by Id filter json_output = json.loads(self.openstack( 'nat dnat rule list -f json ' - '--id ' + self.DNAT_RULE_ID + '--id ' + dnat_rule_id )) self.assertIsNotNone(json_output) - self.assertEqual(next(iter(json_output))['Id'], self.DNAT_RULE_ID) + self.assertEqual(next(iter(json_output))['Id'], dnat_rule_id) self.assertEqual( - next(iter(json_output))['Nat Gateway Id'], self.NAT_ID) + next(iter(json_output))['Nat Gateway Id'], nat_id) - def test_05_nat_dnat_rule_list_by_nat_id(self): - self.assertIsNotNone(self.DNAT_RULE_ID) + # List Dnat Rules by Nat Id filter json_output = json.loads(self.openstack( 'nat dnat rule list -f json ' - '--nat-gateway-id ' + self.NAT_ID + '--nat-gateway-id ' + nat_id )) self.assertIsNotNone(json_output) self.assertEqual( - next(iter(json_output))['Nat Gateway Id'], self.NAT_ID) + next(iter(json_output))['Nat Gateway Id'], nat_id) - def test_06_nat_dnat_rule_show(self): - self.assertIsNotNone(self.DNAT_RULE_ID) + # Show Dnat Rule details json_output = json.loads(self.openstack( 'nat dnat rule show ' - ' -f json ' + self.DNAT_RULE_ID + ' -f json ' + dnat_rule_id )) self.assertIsNotNone(json_output) - self.assertEqual(json_output['id'], self.DNAT_RULE_ID) - - def test_07_nat_dnat_rule_delete(self): - self.addCleanup(self._delete_nat_gateway) - self.assertIsNotNone(self.NAT_ID) - self.assertIsNotNone(self.DNAT_RULE_ID) - self.openstack( - 'nat dnat rule delete ' + self.DNAT_RULE_ID) - - def _create_nat_gateway(self): - self._initialize_network() - json_output = json.loads(self.openstack( - 'nat gateway create {name}' - ' --router-id {router_id}' - ' --internal-network-id {net_id}' - ' --spec {spec} -f json'.format( - name=self.NAT_NAME, - router_id=self.ROUTER_ID, - net_id=self.NETWORK_ID, - description='OTCE Lib Test', - spec=1) - )) - TestDnatRule.NAT_ID = json_output['id'] - - def _delete_nat_gateway(self): - self.addCleanup(self._denitialize_network) - self.openstack('nat gateway delete ' + self.NAT_ID) - - def _initialize_network(self): - router = json.loads(self.openstack( - 'router create -f json ' + self.ROUTER_NAME - )) - network = json.loads(self.openstack( - 'network create -f json ' + self.NETWORK_NAME - )) - self.openstack( - 'subnet create {subnet} -f json ' - '--network {net} ' - '--subnet-range 192.168.0.0/24 '.format( - subnet=self.SUBNET_NAME, - net=self.NETWORK_NAME - )) - - self.openstack( - 'router add subnet {router} ' - '{subnet} '.format( - router=self.ROUTER_NAME, - subnet=self.SUBNET_NAME - ) - ) - - floating_ip = json.loads(self.openstack( - 'floating ip create -f json ' - '{network}'.format( - network='admin_external_net') - )) - - TestDnatRule.ROUTER_ID = router['id'] - TestDnatRule.NETWORK_ID = network['id'] - TestDnatRule.FLOATING_IP_ID = floating_ip['id'] - - port = json.loads(self.openstack( - 'port create {name} ' - '--network {net_id} ' - '-f json'.format( - name=self.PORT_NAME, - net_id=self.NETWORK_ID) - )) - TestDnatRule.PORT_ID = port['id'] - - def _denitialize_network(self): - self.openstack( - 'port delete ' + self.PORT_NAME - ) - self.openstack( - 'router remove subnet {router} ' - '{subnet} '.format( - router=self.ROUTER_NAME, - subnet=self.SUBNET_NAME - ) - ) - self.openstack( - 'subnet delete ' + self.SUBNET_NAME - ) - self.openstack( - 'network delete ' + self.NETWORK_NAME - ) - self.openstack( - 'router delete ' + self.ROUTER_NAME - ) - self.openstack( - 'floating ip delete ' + self.FLOATING_IP_ID - ) + self.assertEqual(json_output['id'], dnat_rule_id) diff --git a/otcextensions/tests/functional/osclient/nat/v2/test_nat_gateway.py b/otcextensions/tests/functional/osclient/nat/v2/test_nat_gateway.py index a0f78e0a0..af6238727 100644 --- a/otcextensions/tests/functional/osclient/nat/v2/test_nat_gateway.py +++ b/otcextensions/tests/functional/osclient/nat/v2/test_nat_gateway.py @@ -11,32 +11,26 @@ # under the License. import json -import uuid -from openstackclient.tests.functional import base +from otcextensions.tests.functional.osclient.nat.v2 import common -class TestNatGateway(base.TestCase): +class TestNatGateway(common.NatTestCase): """Functional Tests for NAT Gateway""" - UUID = uuid.uuid4().hex[:8] - ROUTER_NAME = 'sdk-test-router-' + UUID - NETWORK_NAME = 'sdk-test-net-' + UUID - SUBNET_NAME = 'sdk-test-subnet-' + UUID - ROUTER_ID = None - NETWORK_ID = None + @classmethod + def setUpClass(cls): + super(TestNatGateway, cls).setUpClass() - NAT_NAME = 'os-cli-test-' + UUID - NAT_ID = None - - def test_01_nat_gateway_list(self): - self.openstack( + def test_nat_gateway_list(self): + json_output = json.loads(self.openstack( 'nat gateway list -f json ' - ) + )) + self.assertIsNotNone(json_output) - def test_02_gat_gateway_list_filters(self): - self.openstack( - 'nat gateway list ' + def test_nat_gateway_list_filters(self): + json_output = json.loads(self.openstack( + 'nat gateway list -f json ' '--limit 1 --id 2 ' '--name 3 --spec 4 ' '--router-id 5 ' @@ -44,142 +38,66 @@ def test_02_gat_gateway_list_filters(self): '--project-id 7 ' '--status active ' '--admin-state-up True ' - ) - - def test_03_nat_gateway_create(self): - self._initialize_network() - json_output = json.loads(self.openstack( - 'nat gateway create {name}' - ' --router-id {router_id}' - ' --internal-network-id {net_id}' - ' --spec {spec} -f json'.format( - name=self.NAT_NAME, - router_id=self.ROUTER_ID, - net_id=self.NETWORK_ID, - description='OTCE Lib Test', - spec=1) )) self.assertIsNotNone(json_output) - TestNatGateway.NAT_ID = json_output['id'] - def test_04_nat_gateway_list_by_id(self): + def test_nat_gateway(self): + nat_gateway = self.create_nat_gateway() + nat_id = nat_gateway['id'] + nat_name = nat_gateway['name'] + router_id = nat_gateway['router_id'] + + self.addCleanup(self.delete_nat_gateway) + + # List Nat Gateway By Id json_output = json.loads(self.openstack( 'nat gateway list -f json' - ' --id {}'.format(self.NAT_ID) + ' --id {}'.format(nat_id) )) - self.assertEqual(json_output[0]['Name'], self.NAT_NAME) - self.assertEqual(json_output[0]['Id'], self.NAT_ID) + self.assertEqual(json_output[0]['Name'], nat_name) + self.assertEqual(json_output[0]['Id'], nat_id) - def test_05_nat_gateway_list_by_name(self): + # List Nat Gateway By Name json_output = json.loads(self.openstack( 'nat gateway list -f json' - ' --name {}'.format(self.NAT_NAME) + ' --name {}'.format(nat_name) )) - self.assertEqual(json_output[0]['Name'], self.NAT_NAME) - self.assertEqual(json_output[0]['Id'], self.NAT_ID) + self.assertEqual(json_output[0]['Name'], nat_name) + self.assertEqual(json_output[0]['Id'], nat_id) - def test_06_nat_gateway_list_by_router_id(self): + # List Nat Gateway by Router ID json_output = json.loads(self.openstack( 'nat gateway list -f json' - ' --router-id {}'.format(self.ROUTER_ID) + ' --router-id {}'.format(router_id) )) for nat_gw in json_output: - self.assertEqual(nat_gw['Router Id'], self.ROUTER_ID) + self.assertEqual(nat_gw['Router Id'], router_id) - def test_07_nat_gateway_show_by_name(self): + # Show Nat Gateway by Name json_output = json.loads(self.openstack( - 'nat gateway show -f json ' + self.NAT_NAME + 'nat gateway show -f json ' + nat_name )) - self.assertEqual(json_output['name'], self.NAT_NAME) - self.assertEqual(json_output['id'], self.NAT_ID) + self.assertEqual(json_output['name'], nat_name) + self.assertEqual(json_output['id'], nat_id) - def test_08_nat_gateway_show_by_id(self): + # Show Nat Gateway by Id json_output = json.loads(self.openstack( - 'nat gateway show -f json ' + self.NAT_ID + 'nat gateway show -f json ' + nat_id )) - self.assertEqual(json_output['name'], self.NAT_NAME) - self.assertEqual(json_output['id'], self.NAT_ID) + self.assertEqual(json_output['name'], nat_name) + self.assertEqual(json_output['id'], nat_id) - def test_09_nat_gateway_update_by_id(self): - name = self.NAT_NAME + "-updated" + # Update Nat Gateway + nat_name = nat_name + "-updated" description = "otce cli test nat updated" json_output = json.loads(self.openstack( 'nat gateway update {nat_id} ' '--name {name} ' '--description "{desc}" ' '-f json'.format( - nat_id=self.NAT_ID, - name=name, + nat_id=nat_id, + name=nat_name, desc=description) )) - self.assertEqual(json_output['name'], name) + self.assertEqual(json_output['name'], nat_name) self.assertEqual(json_output['description'], description) - TestNatGateway.NAT_NAME = json_output['name'] - - def test_10_nat_gateway_update_by_name(self): - name = 'os-cli-test-' + self.UUID - description = "otce cli test nat" - spec = '2' - json_output = json.loads(self.openstack( - 'nat gateway update {nat_name} ' - '--name {name} ' - '--description "{desc}" ' - '--spec {spec} ' - '-f json'.format( - nat_name=self.NAT_NAME, - name=name, - spec=spec, - desc=description) - )) - self.assertEqual(json_output['name'], name) - self.assertEqual(json_output['description'], description) - self.assertEqual(json_output['spec'], spec) - TestNatGateway.NAT_NAME = json_output['name'] - - def test_11_nat_gateway_delete(self): - self.addCleanup(self._denitialize_network) - self.openstack('nat gateway delete ' + self.NAT_ID) - - def _initialize_network(self): - router = json.loads(self.openstack( - 'router create -f json ' + self.ROUTER_NAME - )) - network = json.loads(self.openstack( - 'network create -f json ' + self.NETWORK_NAME - )) - self.openstack( - 'subnet create {subnet} -f json ' - '--network {net} ' - '--subnet-range 192.168.0.0/24 '.format( - subnet=self.SUBNET_NAME, - net=self.NETWORK_NAME - )) - - self.openstack( - 'router add subnet {router} ' - '{subnet} '.format( - router=self.ROUTER_NAME, - subnet=self.SUBNET_NAME - ) - ) - - TestNatGateway.ROUTER_ID = router['id'] - TestNatGateway.NETWORK_ID = network['id'] - - def _denitialize_network(self): - self.openstack( - 'router remove subnet {router} ' - '{subnet} '.format( - router=self.ROUTER_NAME, - subnet=self.SUBNET_NAME - ) - ) - self.openstack( - 'subnet delete ' + self.SUBNET_NAME - ) - self.openstack( - 'network delete ' + self.NETWORK_NAME - ) - self.openstack( - 'router delete ' + self.ROUTER_NAME - ) diff --git a/otcextensions/tests/functional/osclient/nat/v2/test_snat_rule.py b/otcextensions/tests/functional/osclient/nat/v2/test_snat_rule.py index 7b46cc1d0..71493389e 100644 --- a/otcextensions/tests/functional/osclient/nat/v2/test_snat_rule.py +++ b/otcextensions/tests/functional/osclient/nat/v2/test_snat_rule.py @@ -11,35 +11,26 @@ # under the License. import json -import uuid -from openstackclient.tests.functional import base -from tempest.lib.exceptions import CommandFailed +from otcextensions.tests.functional.osclient.nat.v2 import common -class TestSnatRule(base.TestCase): +class TestSnatRule(common.NatTestCase): """Functional Tests for NAT Gateway""" - UUID = uuid.uuid4().hex[:8] - ROUTER_NAME = 'sdk-test-router-' + UUID - NETWORK_NAME = 'sdk-test-net-' + UUID - SUBNET_NAME = 'sdk-test-subnet-' + UUID - ROUTER_ID = None - NETWORK_ID = None - FLOATING_IP_ID = None + @classmethod + def setUpClass(cls): + super(TestSnatRule, cls).setUpClass() - NAT_NAME = 'os-cli-test-' + UUID - NAT_ID = None - SNAT_RULE_ID = None - - def test_01_snat_rule_list(self): - self.openstack( + def test_snat_rule_list(self): + json_output = json.loads(self.openstack( 'nat snat rule list -f json ' - ) + )) + self.assertIsNotNone(json_output) - def test_02_snat_rule_list_filters(self): - self.openstack( - 'nat snat rule list ' + def test_snat_rule_list_filters(self): + json_output = json.loads(self.openstack( + 'nat snat rule list -f json ' '--limit 1 --id 2 ' '--project-id 3 ' '--nat-gateway-id 4 ' @@ -50,46 +41,35 @@ def test_02_snat_rule_list_filters(self): '--floating-ip-address 9 ' '--status 10 ' '--admin-state-up true ' - ) - - def test_03_nat_snat_rule_create(self): - self._create_nat_gateway() - self.assertIsNotNone(self.NAT_ID) - self.assertIsNotNone(self.FLOATING_IP_ID) - json_output = json.loads(self.openstack( - 'nat snat rule create ' - '--nat-gateway-id {nat_gateway_id} ' - '--floating-ip-id {floating_ip_id} ' - '--network-id {net_id} -f json'.format( - nat_gateway_id=self.NAT_ID, - floating_ip_id=self.FLOATING_IP_ID, - net_id=self.NETWORK_ID) )) self.assertIsNotNone(json_output) - TestSnatRule.SNAT_RULE_ID = json_output['id'] - def test_04_nat_snat_rule_list_by_id(self): - self.assertIsNotNone(self.SNAT_RULE_ID) + def test_nat_snat_rule_create(self): + json_output = self.create_snat_rule() + self.addCleanup(self.delete_snat_rule) + snat_rule_id = json_output['id'] + nat_id = json_output['nat_gateway_id'] + + # List Snat Rule by Snat Id filter json_output = json.loads(self.openstack( 'nat snat rule list -f json ' - '--id ' + self.SNAT_RULE_ID + '--id ' + snat_rule_id )) self.assertIsNotNone(json_output) - self.assertEqual(next(iter(json_output))['Id'], self.SNAT_RULE_ID) + self.assertEqual(next(iter(json_output))['Id'], snat_rule_id) self.assertEqual( - next(iter(json_output))['Nat Gateway Id'], self.NAT_ID) + next(iter(json_output))['Nat Gateway Id'], nat_id) - def test_05_nat_snat_rule_list_by_nat_id(self): - self.assertIsNotNone(self.SNAT_RULE_ID) + # List Snat Rule by nat-gateway-id filter json_output = json.loads(self.openstack( 'nat snat rule list -f json ' - '--nat-gateway-id ' + self.NAT_ID + '--nat-gateway-id ' + nat_id )) self.assertIsNotNone(json_output) self.assertEqual( - next(iter(json_output))['Nat Gateway Id'], self.NAT_ID) + next(iter(json_output))['Nat Gateway Id'], nat_id) - def test_06_nat_snat_rule_show(self): + # Show Snat Rule by Id self.assertIsNotNone(self.SNAT_RULE_ID) json_output = json.loads(self.openstack( 'nat snat rule show ' @@ -97,118 +77,3 @@ def test_06_nat_snat_rule_show(self): )) self.assertIsNotNone(json_output) self.assertEqual(json_output['id'], self.SNAT_RULE_ID) - - def test_07_nat_snat_rule_create_for_existing_network(self): - self.assertIsNotNone(self.NAT_ID) - self.assertIsNotNone(self.FLOATING_IP_ID) - self.assertRaises( - CommandFailed, - self.openstack, - 'nat snat rule create ' - '{nat_id} {floating_ip_id} ' - '--network-id {net_id} -f json'.format( - nat_id=self.NAT_ID, - floating_ip_id=self.FLOATING_IP_ID, - net_id=self.NETWORK_ID) - ) - - def test_08_nat_snat_rule_create_cidr_source_type(self): - self.assertIsNotNone(self.NAT_ID) - self.assertIsNotNone(self.FLOATING_IP_ID) - cidr = '192.168.5.0/24' - source_type = 1 - json_output = json.loads(self.openstack( - 'nat snat rule create ' - '--nat-gateway-id {nat_gateway_id} ' - '--floating-ip-id {floating_ip_id} ' - '--source-type {source_type} ' - '--cidr {cidr} -f json'.format( - nat_gateway_id=self.NAT_ID, - floating_ip_id=self.FLOATING_IP_ID, - source_type=source_type, - cidr=cidr) - )) - self.assertEqual(json_output['source_type'], source_type) - self.assertEqual(json_output['cidr'], cidr) - self.openstack( - 'nat snat rule delete ' + json_output['id']) - - def test_09_nat_snat_rule_delete(self): - self.addCleanup(self._delete_nat_gateway) - self.assertIsNotNone(self.NAT_ID) - self.assertIsNotNone(self.SNAT_RULE_ID) - self.openstack( - 'nat snat rule delete ' + self.SNAT_RULE_ID) - - def _create_nat_gateway(self): - self._initialize_network() - json_output = json.loads(self.openstack( - 'nat gateway create {name}' - ' --router-id {router_id}' - ' --internal-network-id {net_id}' - ' --spec {spec} -f json'.format( - name=self.NAT_NAME, - router_id=self.ROUTER_ID, - net_id=self.NETWORK_ID, - description='OTCE Lib Test', - spec=1) - )) - TestSnatRule.NAT_ID = json_output['id'] - - def _delete_nat_gateway(self): - self.addCleanup(self._denitialize_network) - self.openstack('nat gateway delete ' + self.NAT_ID) - - def _initialize_network(self): - router = json.loads(self.openstack( - 'router create -f json ' + self.ROUTER_NAME - )) - net = json.loads(self.openstack( - 'network create -f json ' + self.NETWORK_NAME - )) - self.openstack( - 'subnet create {subnet} -f json ' - '--network {net} ' - '--subnet-range 192.168.0.0/24 '.format( - subnet=self.SUBNET_NAME, - net=self.NETWORK_NAME - )) - - self.openstack( - 'router add subnet {router} ' - '{subnet} '.format( - router=self.ROUTER_NAME, - subnet=self.SUBNET_NAME - ) - ) - - floating_ip = json.loads(self.openstack( - 'floating ip create -f json ' - '{network}'.format( - network='admin_external_net') - )) - - TestSnatRule.ROUTER_ID = router['id'] - TestSnatRule.NETWORK_ID = net['id'] - TestSnatRule.FLOATING_IP_ID = floating_ip['id'] - - def _denitialize_network(self): - self.openstack( - 'router remove subnet {router} ' - '{subnet} '.format( - router=self.ROUTER_NAME, - subnet=self.SUBNET_NAME - ) - ) - self.openstack( - 'subnet delete ' + self.SUBNET_NAME - ) - self.openstack( - 'network delete ' + self.NETWORK_NAME - ) - self.openstack( - 'router delete ' + self.ROUTER_NAME - ) - self.openstack( - 'floating ip delete ' + self.FLOATING_IP_ID - ) From aff0daec1b1a4139f4fda623dd67996991745ab7 Mon Sep 17 00:00:00 2001 From: Vineet Pruthi Date: Thu, 2 Apr 2020 09:34:48 +0000 Subject: [PATCH 64/73] Fixes in Functional Tests --- .../tests/functional/osclient/nat/v2/common.py | 12 ++++++++---- .../functional/osclient/nat/v2/test_dnat_rule.py | 1 + .../functional/osclient/nat/v2/test_nat_gateway.py | 1 + .../functional/osclient/nat/v2/test_snat_rule.py | 1 + otcextensions/tests/unit/osclient/nat/v2/fakes.py | 6 +++--- 5 files changed, 14 insertions(+), 7 deletions(-) diff --git a/otcextensions/tests/functional/osclient/nat/v2/common.py b/otcextensions/tests/functional/osclient/nat/v2/common.py index 3669b3925..78c166c67 100644 --- a/otcextensions/tests/functional/osclient/nat/v2/common.py +++ b/otcextensions/tests/functional/osclient/nat/v2/common.py @@ -14,19 +14,23 @@ import json import uuid +from datetime import datetime + from openstackclient.tests.functional import base class NatTestCase(base.TestCase): """Common functional test bits for NAT commands""" - UUID = uuid.uuid4().hex[:8] - ROUTER_NAME = 'sdk-test-router-' + UUID - NETWORK_NAME = 'sdk-test-net-' + UUID - SUBNET_NAME = 'sdk-test-subnet-' + UUID + CURR_TIME = datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f") def setUp(self): super(NatTestCase, self).setUp() + UUID = uuid.uuid4().hex[:8] + self.ROUTER_NAME = 'sdk-test-router-' + UUID + self.NETWORK_NAME = 'sdk-test-net-' + UUID + self.SUBNET_NAME = 'sdk-test-subnet-' + UUID + self.ROUTER_ID = None self.NETWORK_ID = None self.FLOATING_IP_ID = None diff --git a/otcextensions/tests/functional/osclient/nat/v2/test_dnat_rule.py b/otcextensions/tests/functional/osclient/nat/v2/test_dnat_rule.py index d09b40084..15cc511ec 100644 --- a/otcextensions/tests/functional/osclient/nat/v2/test_dnat_rule.py +++ b/otcextensions/tests/functional/osclient/nat/v2/test_dnat_rule.py @@ -43,6 +43,7 @@ def test_nat_dnat_rule_list_filters(self): '--nat-gateway-id 11 ' '--protocol tcp ' '--admin-state-up true ' + '--created-at "{}"'.format(self.CURR_TIME) )) self.assertIsNotNone(json_output) diff --git a/otcextensions/tests/functional/osclient/nat/v2/test_nat_gateway.py b/otcextensions/tests/functional/osclient/nat/v2/test_nat_gateway.py index af6238727..5450a131a 100644 --- a/otcextensions/tests/functional/osclient/nat/v2/test_nat_gateway.py +++ b/otcextensions/tests/functional/osclient/nat/v2/test_nat_gateway.py @@ -38,6 +38,7 @@ def test_nat_gateway_list_filters(self): '--project-id 7 ' '--status active ' '--admin-state-up True ' + '--created-at "{}"'.format(self.CURR_TIME) )) self.assertIsNotNone(json_output) diff --git a/otcextensions/tests/functional/osclient/nat/v2/test_snat_rule.py b/otcextensions/tests/functional/osclient/nat/v2/test_snat_rule.py index 71493389e..f396b45ad 100644 --- a/otcextensions/tests/functional/osclient/nat/v2/test_snat_rule.py +++ b/otcextensions/tests/functional/osclient/nat/v2/test_snat_rule.py @@ -41,6 +41,7 @@ def test_snat_rule_list_filters(self): '--floating-ip-address 9 ' '--status 10 ' '--admin-state-up true ' + '--created-at "{}"'.format(self.CURR_TIME) )) self.assertIsNotNone(json_output) diff --git a/otcextensions/tests/unit/osclient/nat/v2/fakes.py b/otcextensions/tests/unit/osclient/nat/v2/fakes.py index b79f0c48d..060916b34 100644 --- a/otcextensions/tests/unit/osclient/nat/v2/fakes.py +++ b/otcextensions/tests/unit/osclient/nat/v2/fakes.py @@ -63,7 +63,7 @@ def generate(cls): "description": "my nat gateway", "admin_state_up": 'true', "tenant_id": "tenant-id-" + uuid.uuid4().hex, - "created_at": datetime.now().strftime("%Y-%m-%d %H:%M:%s")[:-4], + "created_at": datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f"), "spec": "1", "internal_network_id": "net-id-" + uuid.uuid4().hex } @@ -109,7 +109,7 @@ def generate(cls): "cidr": uuid.uuid4().hex, "source_type": 0, "tenant_id": "tenant-id-" + uuid.uuid4().hex, - "created_at": datetime.now().strftime("%Y-%m-%d %H:%M:%s")[:-4], + "created_at": datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f"), "floating_ip_address": uuid.uuid4().hex } @@ -148,7 +148,7 @@ def generate(cls): "protocol": "any", "tenant_id": "abc", "port_id": "", - "created_at": datetime.now().strftime("%Y-%m-%d %H:%M:%s")[:-4], + "created_at": datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f"), "floating_ip_address": uuid.uuid4().hex, "external_service_port": 0 } From 20ea6d8ca467382c862cacf3aea29af7ac2f1c9a Mon Sep 17 00:00:00 2001 From: Vineet Pruthi Date: Thu, 2 Apr 2020 14:11:07 +0000 Subject: [PATCH 65/73] Updated Line breaks for help --- otcextensions/osclient/nat/v2/dnat.py | 20 ++++----- otcextensions/osclient/nat/v2/gateway.py | 52 ++++++++++++------------ otcextensions/osclient/nat/v2/snat.py | 32 +++++++-------- 3 files changed, 52 insertions(+), 52 deletions(-) diff --git a/otcextensions/osclient/nat/v2/dnat.py b/otcextensions/osclient/nat/v2/dnat.py index 84da45469..dbc33501b 100644 --- a/otcextensions/osclient/nat/v2/dnat.py +++ b/otcextensions/osclient/nat/v2/dnat.py @@ -106,21 +106,21 @@ def get_parser(self, prog_name): parser.add_argument( '--status', metavar='', - help=_("Specifies the status of the DNAT rule." - "\nACTIVE: The resource status is normal." - "\nPENDING_CREATE: The resource is being created." - "\nPENDING_UPDATE: The resource is being updated." - "\nPENDING_DELETE: The resource is being deleted." - "\nEIP_FREEZED: The EIP of the resource is frozen." - "\nINACTIVE: The resource status is abnormal."), + help=_("Specifies the status of the DNAT rule.\n" + "ACTIVE: The resource status is normal.\n" + "PENDING_CREATE: The resource is being created.\n" + "PENDING_UPDATE: The resource is being updated.\n" + "PENDING_DELETE: The resource is being deleted.\n" + "EIP_FREEZED: The EIP of the resource is frozen.\n" + "INACTIVE: The resource status is abnormal."), ) parser.add_argument( '--admin-state-up', metavar='', help=_("Specifies whether the DNAT rule is enabled or " - "disabled. The value can be:" - "\ntrue: The DNAT rule is enabled." - "\nfalse: The DNAT rule is disabled."), + "disabled. The value can be:\n" + "true: The DNAT rule is enabled.\n" + "false: The DNAT rule is disabled."), ) parser.add_argument( '--created-at', diff --git a/otcextensions/osclient/nat/v2/gateway.py b/otcextensions/osclient/nat/v2/gateway.py index c0bed553c..6fbf913bb 100644 --- a/otcextensions/osclient/nat/v2/gateway.py +++ b/otcextensions/osclient/nat/v2/gateway.py @@ -61,14 +61,14 @@ def get_parser(self, prog_name): '--spec', metavar='', help=_("Specifies the type of the NAT Gateway. " - "The value of spec can be:" - "\n1: small type, which supports up to 10,000 " - "SNAT connections." - "\n2: medium type, which supports up to 50,000 " - "SNAT connections." - "\n3: large type, which supports up to 200,000 " - "SNAT connections." - "\n4: extra-large type, which supports up to " + "The value of spec can be:\n" + "1: small type, which supports up to 10,000 " + "SNAT connections.\n" + "2: medium type, which supports up to 50,000 " + "SNAT connections.\n" + "3: large type, which supports up to 200,000 " + "SNAT connections.\n" + "4: extra-large type, which supports up to " "1,000,000 SNAT connections."), ) parser.add_argument( @@ -86,21 +86,21 @@ def get_parser(self, prog_name): parser.add_argument( '--status', metavar='', - help=_("Specifies the status of the NAT Gateway." - "\nACTIVE: The resource status is normal." - "\nPENDING_CREATE: The resource is being created." - "\nPENDING_UPDATE: The resource is being updated." - "\nPENDING_DELETE: The resource is being deleted." - "\nEIP_FREEZED: The EIP of the resource is frozen." - "\nINACTIVE: The resource status is abnormal."), + help=_("Specifies the status of the NAT Gateway.\n" + "ACTIVE: The resource status is normal.\n" + "PENDING_CREATE: The resource is being created.\n" + "PENDING_UPDATE: The resource is being updated.\n" + "PENDING_DELETE: The resource is being deleted.\n" + "EIP_FREEZED: The EIP of the resource is frozen.\n" + "INACTIVE: The resource status is abnormal."), ) parser.add_argument( '--admin-state-up', metavar='', help=_("Specifies whether the NAT Gateway is enabled " - "or disabled. The value can be:" - "\ntrue: The NAT gateway is up." - "\nfalse: The NAT gateway is down."), + "or disabled. The value can be:\n" + "true: The NAT gateway is up.\n" + "false: The NAT gateway is down."), ) parser.add_argument( '--created-at', @@ -179,14 +179,14 @@ def get_parser(self, prog_name): required=True, help=_( "Specifies the type of the NAT Gateway. " - "The value can be:" - "\n1: small type, which supports up to 10,000 " - "SNAT connections." - "\n2: medium type, which supports up to 50,000 " - "SNAT connections." - "\n3: large type, which supports up to 200,000 " - "SNAT connections." - "\n4: extra-large type, which supports up to " + "The value can be:\n" + "1: small type, which supports up to 10,000 " + "SNAT connections.\n" + "2: medium type, which supports up to 50,000 " + "SNAT connections.\n" + "3: large type, which supports up to 200,000 " + "SNAT connections.\n" + "4: extra-large type, which supports up to " "1,000,000 SNAT connections."), ) parser.add_argument( diff --git a/otcextensions/osclient/nat/v2/snat.py b/otcextensions/osclient/nat/v2/snat.py index edcd1b1a5..4a710491b 100644 --- a/otcextensions/osclient/nat/v2/snat.py +++ b/otcextensions/osclient/nat/v2/snat.py @@ -93,21 +93,21 @@ def get_parser(self, prog_name): parser.add_argument( '--status', metavar='', - help=_("Specifies the status of the SNAT rule." - "\nACTIVE: The resource status is normal." - "\nPENDING_CREATE: The resource is being created." - "\nPENDING_UPDATE: The resource is being updated." - "\nPENDING_DELETE: The resource is being deleted." - "\nEIP_FREEZED: The EIP of the resource is frozen." - "\nINACTIVE: The resource status is abnormal."), + help=_("Specifies the status of the SNAT rule.\n" + "ACTIVE: The resource status is normal.\n" + "PENDING_CREATE: The resource is being created.\n" + "PENDING_UPDATE: The resource is being updated.\n" + "PENDING_DELETE: The resource is being deleted.\n" + "EIP_FREEZED: The EIP of the resource is frozen.\n" + "INACTIVE: The resource status is abnormal."), ) parser.add_argument( '--admin-state-up', metavar='', help=_("Specifies whether the SNAT rule is enabled or " - "disabled. The value can be:" - "\ntrue: The SNAT rule is enabled." - "\nfalse: The SNAT rule is disabled."), + "disabled. The value can be:\n" + "true: The SNAT rule is enabled.\n" + "false: The SNAT rule is disabled."), ) parser.add_argument( '--created-at', @@ -207,12 +207,12 @@ def get_parser(self, prog_name): '--source-type', metavar='', help=_( - "Specifies the source type." - "\n0: Either network_id or cidr can be " - "specified in a VPC." - "\n1: Only cidr can be specified over a " - "Direct Connect connection." - "\nIf no value is entered, the default " + "Specifies the source type.\n" + "0: Either network_id or cidr can be " + "specified in a VPC.\n" + "1: Only cidr can be specified over a " + "Direct Connect connection.\n" + "If no value is entered, the default " "value 0 (VPC) is used."), ) return parser From 508502c0885e7004afb4ec9abfe9c8bd580e33a8 Mon Sep 17 00:00:00 2001 From: Vineet Pruthi Date: Fri, 3 Apr 2020 09:44:23 +0000 Subject: [PATCH 66/73] Added multiple delete support --- otcextensions/osclient/nat/v2/dnat.py | 21 +++- otcextensions/osclient/nat/v2/gateway.py | 22 +++- otcextensions/osclient/nat/v2/snat.py | 21 +++- otcextensions/sdk/nat/v2/_proxy.py | 10 +- .../functional/osclient/nat/v2/common.py | 9 +- .../tests/unit/osclient/nat/v2/fakes.py | 51 --------- .../tests/unit/osclient/nat/v2/test_dnat.py | 92 +++++++++++----- .../unit/osclient/nat/v2/test_gateway.py | 100 +++++++++++------- .../tests/unit/osclient/nat/v2/test_snat.py | 95 ++++++++++++----- 9 files changed, 261 insertions(+), 160 deletions(-) diff --git a/otcextensions/osclient/nat/v2/dnat.py b/otcextensions/osclient/nat/v2/dnat.py index dbc33501b..d241a650f 100644 --- a/otcextensions/osclient/nat/v2/dnat.py +++ b/otcextensions/osclient/nat/v2/dnat.py @@ -14,6 +14,7 @@ import logging from osc_lib import utils +from osc_lib import exceptions from osc_lib.command import command from otcextensions.i18n import _ @@ -272,11 +273,25 @@ def get_parser(self, prog_name): parser.add_argument( 'dnat', metavar='', - help=_("Specifies the ID of the DNAT Rule."), + nargs='+', + help=_("Specifies the DNAT Rule(s) ID(s) to delete."), ) return parser def take_action(self, parsed_args): client = self.app.client_manager.nat - dnat_rule = client.get_dnat_rule(parsed_args.dnat) - client.delete_dnat_rule(dnat_rule.id) + result = 0 + for dnat in parsed_args.dnat: + try: + obj = client.get_dnat_rule(dnat) + client.delete_dnat_rule(obj.id) + except Exception as e: + result += 1 + LOG.error(_("Failed to delete DNAT rule with " + "ID '%(dnat)s': %(e)s"), + {'dnat': dnat, 'e': e}) + if result > 0: + total = len(parsed_args.dnat) + msg = (_("%(result)s of %(total)s DNAT Rule(s) failed " + "to delete.") % {'result': result, 'total': total}) + raise exceptions.CommandError(msg) diff --git a/otcextensions/osclient/nat/v2/gateway.py b/otcextensions/osclient/nat/v2/gateway.py index 6fbf913bb..37f34be56 100644 --- a/otcextensions/osclient/nat/v2/gateway.py +++ b/otcextensions/osclient/nat/v2/gateway.py @@ -14,6 +14,7 @@ import logging from osc_lib import utils +from osc_lib import exceptions from osc_lib.command import command from otcextensions.i18n import _ @@ -151,6 +152,7 @@ def get_parser(self, prog_name): def take_action(self, parsed_args): client = self.app.client_manager.nat obj = client.find_gateway(parsed_args.gateway) + display_columns, columns = _get_columns(obj) data = utils.get_item_properties(obj, columns) @@ -282,11 +284,25 @@ def get_parser(self, prog_name): parser.add_argument( 'gateway', metavar='', - help=_("Specifies the Name or ID of the NAT Gateway."), + nargs='+', + help=_("Nat Gateway(s) to delete (Name or ID)"), ) return parser def take_action(self, parsed_args): client = self.app.client_manager.nat - nat_gateway = client.find_gateway(parsed_args.gateway) - client.delete_gateway(nat_gateway.id) + result = 0 + for gateway in parsed_args.gateway: + try: + obj = client.find_gateway(gateway) + client.delete_gateway(obj.id) + except Exception as e: + result += 1 + LOG.error(_("Failed to delete Nat Gateway with " + "name or ID '%(gateway)s': %(e)s"), + {'gateway': gateway, 'e': e}) + if result > 0: + total = len(parsed_args.gateway) + msg = (_("%(result)s of %(total)s NAT Gateway(s) failed " + "to delete.") % {'result': result, 'total': total}) + raise exceptions.CommandError(msg) diff --git a/otcextensions/osclient/nat/v2/snat.py b/otcextensions/osclient/nat/v2/snat.py index 4a710491b..4dc54cabe 100644 --- a/otcextensions/osclient/nat/v2/snat.py +++ b/otcextensions/osclient/nat/v2/snat.py @@ -14,6 +14,7 @@ import logging from osc_lib import utils +from osc_lib import exceptions from osc_lib.command import command from otcextensions.i18n import _ @@ -250,12 +251,26 @@ def get_parser(self, prog_name): parser.add_argument( 'snat', metavar='', - help=_("Specifies the ID of the SNAT Rule."), + nargs='+', + help=_("Specifies the SNAT rule(s) ID(s) to delete."), ) return parser def take_action(self, parsed_args): client = self.app.client_manager.nat - snat_rule = client.get_snat_rule(parsed_args.snat) - client.delete_snat_rule(snat_rule.id) + result = 0 + for snat in parsed_args.snat: + try: + obj = client.get_snat_rule(snat) + client.delete_snat_rule(obj.id) + except Exception as e: + result += 1 + LOG.error(_("Failed to delete SNAT rule with " + "ID '%(snat)s': %(e)s"), + {'snat': snat, 'e': e}) + if result > 0: + total = len(parsed_args.snat) + msg = (_("%(result)s of %(total)s SNAT Rule(s) failed " + "to delete.") % {'result': result, 'total': total}) + raise exceptions.CommandError(msg) diff --git a/otcextensions/sdk/nat/v2/_proxy.py b/otcextensions/sdk/nat/v2/_proxy.py index 23b508e9e..5f994c2d8 100644 --- a/otcextensions/sdk/nat/v2/_proxy.py +++ b/otcextensions/sdk/nat/v2/_proxy.py @@ -83,7 +83,7 @@ def update_gateway(self, gateway, **attrs): """ return self._update(_gateway.Gateway, gateway, **attrs) - def find_gateway(self, name_or_id, ignore_missing=True): + def find_gateway(self, name_or_id, ignore_missing=False): """Find a single Nat Gateway :param name_or_id: The name or ID of a zone @@ -95,12 +95,8 @@ def find_gateway(self, name_or_id, ignore_missing=True): :returns: ``None`` """ - obj = self._find(_gateway.Gateway, name_or_id) - if obj is None: - raise RuntimeError( - 'The provide NAT Gateway id/name={} ' - 'could not be found'.format(name_or_id)) - return obj + return self._find(_gateway.Gateway, name_or_id, + ignore_missing=ignore_missing) # ======== SNAT rules ======== def create_snat_rule(self, **attrs): diff --git a/otcextensions/tests/functional/osclient/nat/v2/common.py b/otcextensions/tests/functional/osclient/nat/v2/common.py index 78c166c67..0336922da 100644 --- a/otcextensions/tests/functional/osclient/nat/v2/common.py +++ b/otcextensions/tests/functional/osclient/nat/v2/common.py @@ -27,9 +27,10 @@ class NatTestCase(base.TestCase): def setUp(self): super(NatTestCase, self).setUp() UUID = uuid.uuid4().hex[:8] - self.ROUTER_NAME = 'sdk-test-router-' + UUID - self.NETWORK_NAME = 'sdk-test-net-' + UUID - self.SUBNET_NAME = 'sdk-test-subnet-' + UUID + self.ROUTER_NAME = 'otce-nat-test-router-' + UUID + self.NETWORK_NAME = 'otce-nat-test-net-' + UUID + self.SUBNET_NAME = 'otce-nat-test-subnet-' + UUID + self.NAT_NAME = 'otce-nat-test-' + UUID self.ROUTER_ID = None self.NETWORK_ID = None @@ -40,7 +41,7 @@ def setUp(self): def create_nat_gateway(self, name=None): self._initialize_network() - name = name or uuid.uuid4().hex + name = name or self.SUBNET_NAME json_output = json.loads(self.openstack( 'nat gateway create {name}' ' --router-id {router_id}' diff --git a/otcextensions/tests/unit/osclient/nat/v2/fakes.py b/otcextensions/tests/unit/osclient/nat/v2/fakes.py index 060916b34..1291c36bb 100644 --- a/otcextensions/tests/unit/osclient/nat/v2/fakes.py +++ b/otcextensions/tests/unit/osclient/nat/v2/fakes.py @@ -70,23 +70,6 @@ def generate(cls): return gateway.Gateway(**object_info) - @staticmethod - def find_gateway(nat_gateway, name_or_id): - """Get a Mock object with faked nat_gateway. - :param nat_gateway: - A FakeResource objects faking nat_gateway - :param name_or_id: - name or id of nat_gateway - :return: - A Mock object with faked nat_gateway or - side_effect=RuntimeError if name or id - doesnt matches in faked nat_gateway - """ - if name_or_id in [nat_gateway.id, nat_gateway.name]: - return mock.Mock(return_value=nat_gateway) - else: - return mock.Mock(side_effect=RuntimeError('404 Not Found')) - class FakeSnatRule(test_base.Fake): """Fake one or more Instance.""" @@ -115,23 +98,6 @@ def generate(cls): return snat.Snat.existing(**object_info) - @staticmethod - def get_snat_rule(snat_rule, snat_rule_id): - """Get a Mock object with faked snat_rule. - :param snat_rule: - A FakeResource objects faking snat_rule - :param snat_rule_id: - Id of snat_rule - :return: - A Mock object with faked snat_rule or - side_effect=RuntimeError if snat_rule_id - doesnt matches in faked snat_rule Id - """ - if snat_rule.id == snat_rule_id: - return mock.Mock(return_value=snat_rule) - else: - return mock.Mock(side_effect=RuntimeError('404 Not Found')) - class FakeDnatRule(test_base.Fake): """Fake one or more Backup""" @@ -155,20 +121,3 @@ def generate(cls): obj = dnat.Dnat.existing(**object_info) return obj - - @staticmethod - def get_dnat_rule(dnat_rule, dnat_rule_id): - """Get a Mock object with faked dnat_rule. - :param dnat_rule: - A FakeResource objects faking dnat_rule - :param dnat_rule_id: - Id of dnat_rule - :return: - A Mock object with faked snat_rule or - side_effect=RuntimeError if dnat_rule_id - doesnt matches in faked dnat_rule Id - """ - if dnat_rule.id == dnat_rule_id: - return mock.Mock(return_value=dnat_rule) - else: - return mock.Mock(side_effect=RuntimeError('404 Not Found')) diff --git a/otcextensions/tests/unit/osclient/nat/v2/test_dnat.py b/otcextensions/tests/unit/osclient/nat/v2/test_dnat.py index 99ee0f5c2..393eb69cd 100644 --- a/otcextensions/tests/unit/osclient/nat/v2/test_dnat.py +++ b/otcextensions/tests/unit/osclient/nat/v2/test_dnat.py @@ -11,10 +11,15 @@ # under the License. # import mock +from unittest.mock import call + +from osc_lib import exceptions from otcextensions.osclient.nat.v2 import dnat from otcextensions.tests.unit.osclient.nat.v2 import fakes +from openstackclient.tests.unit import utils as tests_utils + class TestListDnatRules(fakes.TestNat): @@ -162,8 +167,16 @@ def setUp(self): self.cmd = dnat.ShowDnatRule(self.app, None) - self.client.get_dnat_rule = ( - fakes.FakeDnatRule.get_dnat_rule(self._data, self._data.id)) + self.client.get_dnat_rule = mock.Mock(return_value=self._data) + + def test_show_no_options(self): + arglist = [] + verifylist = [] + + # Testing that a call without the required argument will fail and + # throw a "ParserExecption" + self.assertRaises(tests_utils.ParserException, + self.check_parser, self.cmd, arglist, verifylist) def test_show(self): arglist = [ @@ -190,23 +203,23 @@ def test_show_non_existent(self): ] verifylist = [ - ('dnat', 'unexist_dnat_rule_id'), + ('dnat', arglist[0]), ] # Verify cm is triggered with default parameters parsed_args = self.check_parser(self.cmd, arglist, verifylist) + find_mock_result = exceptions.CommandError('Resource Not Found') self.client.get_dnat_rule = ( - fakes.FakeDnatRule.get_dnat_rule( - self._data, 'unexist_dnat_rule_id')) + mock.Mock(side_effect=find_mock_result) + ) # Trigger the action try: self.cmd.take_action(parsed_args) - self.fail('CommandError should be raised.') except Exception as e: - self.assertEqual('404 Not Found', str(e)) - self.client.get_dnat_rule.assert_called_with('unexist_dnat_rule_id') + self.assertEqual('Resource Not Found', str(e)) + self.client.get_dnat_rule.assert_called_with(arglist[0]) class TestCreateDnatRule(fakes.TestNat): @@ -276,56 +289,87 @@ def test_create(self): class TestDeleteDnatRule(fakes.TestNat): - _data = fakes.FakeDnatRule.create_one() + _data = fakes.FakeDnatRule.create_multiple(2) def setUp(self): super(TestDeleteDnatRule, self).setUp() - self.client.get_dnat_rule = ( - fakes.FakeDnatRule.get_dnat_rule(self._data, self._data.id)) self.client.delete_dnat_rule = mock.Mock(return_value=None) self.cmd = dnat.DeleteDnatRule(self.app, None) def test_delete(self): arglist = [ - self._data.id, + self._data[0].id, ] verifylist = [ - ('dnat', self._data.id), + ('dnat', arglist), ] # Verify cm is triggered with default parameters parsed_args = self.check_parser(self.cmd, arglist, verifylist) + self.client.get_dnat_rule = ( + mock.Mock(return_value=self._data[0]) + ) + # Trigger the action - self.cmd.take_action(parsed_args) + result = self.cmd.take_action(parsed_args) + self.client.get_dnat_rule.assert_called_with(self._data[0].id) + self.client.delete_dnat_rule.assert_called_with(self._data[0].id) + self.assertIsNone(result) - self.client.get_dnat_rule.assert_called_with(self._data.id) + def test_multiple_delete(self): + arglist = [] + + for dnat_rule in self._data: + arglist.append(dnat_rule.id) + + verifylist = [ + ('dnat', arglist), + ] + + # Verify cm is triggered with default parameters + parsed_args = self.check_parser(self.cmd, arglist, verifylist) - self.client.delete_dnat_rule.assert_called_with(self._data.id) + find_mock_result = self._data + self.client.get_dnat_rule = ( + mock.Mock(side_effect=find_mock_result) + ) + + # Trigger the action + result = self.cmd.take_action(parsed_args) - def test_delete_non_existent(self): + calls = [] + for dnat_rule in self._data: + calls.append(call(dnat_rule.id)) + self.client.delete_dnat_rule.assert_has_calls(calls) + self.assertIsNone(result) + + def test_multiple_delete_with_exception(self): arglist = [ + self._data[0].id, 'unexist_dnat_rule_id', ] - verifylist = [ - ('dnat', 'unexist_dnat_rule_id'), + ('dnat', arglist), ] # Verify cm is triggered with default parameters parsed_args = self.check_parser(self.cmd, arglist, verifylist) + find_mock_result = [self._data[0], exceptions.CommandError] self.client.get_dnat_rule = ( - fakes.FakeDnatRule.get_dnat_rule( - self._data, 'unexist_dnat_rule_id')) + mock.Mock(side_effect=find_mock_result) + ) # Trigger the action try: self.cmd.take_action(parsed_args) - self.fail('CommandError should be raised.') except Exception as e: - self.assertEqual('404 Not Found', str(e)) - self.client.get_dnat_rule.assert_called_with('unexist_dnat_rule_id') + self.assertEqual('1 of 2 DNAT Rule(s) failed to delete.', str(e)) + + self.client.get_dnat_rule.assert_any_call(arglist[0]) + self.client.get_dnat_rule.assert_any_call(arglist[1]) + self.client.delete_dnat_rule.assert_called_once_with(arglist[0]) diff --git a/otcextensions/tests/unit/osclient/nat/v2/test_gateway.py b/otcextensions/tests/unit/osclient/nat/v2/test_gateway.py index cc1f054c2..ec5435e47 100644 --- a/otcextensions/tests/unit/osclient/nat/v2/test_gateway.py +++ b/otcextensions/tests/unit/osclient/nat/v2/test_gateway.py @@ -11,10 +11,15 @@ # under the License. # import mock +from unittest.mock import call + +from osc_lib import exceptions from otcextensions.osclient.nat.v2 import gateway from otcextensions.tests.unit.osclient.nat.v2 import fakes +from openstackclient.tests.unit import utils as tests_utils + class TestListNatGateways(fakes.TestNat): @@ -185,6 +190,7 @@ def setUp(self): self.cmd = gateway.UpdateNatGateway(self.app, None) + self.client.find_gateway = mock.Mock(return_value=self._data) self.client.update_gateway = mock.Mock(return_value=self._data) def test_update(self): @@ -203,9 +209,6 @@ def test_update(self): # Verify cm is triggereg with default parameters parsed_args = self.check_parser(self.cmd, arglist, verifylist) - self.client.find_gateway = ( - fakes.FakeNatGateway.find_gateway(self._data, self._data.name)) - # Trigger the action columns, data = self.cmd.take_action(parsed_args) @@ -243,6 +246,17 @@ def setUp(self): self.cmd = gateway.ShowNatGateway(self.app, None) + self.client.find_gateway = mock.Mock(return_value=self._data) + + def test_show_no_options(self): + arglist = [] + verifylist = [] + + # Testing that a call without the required argument will fail and + # throw a "ParserExecption" + self.assertRaises(tests_utils.ParserException, + self.check_parser, self.cmd, arglist, verifylist) + def test_show(self): arglist = [ self._data.id, @@ -255,9 +269,6 @@ def test_show(self): # Verify cm is triggered with default parameters parsed_args = self.check_parser(self.cmd, arglist, verifylist) - self.client.find_gateway = ( - fakes.FakeNatGateway.find_gateway(self._data, self._data.id)) - # Trigger the action columns, data = self.cmd.take_action(parsed_args) self.client.find_gateway.assert_called_with(self._data.id) @@ -277,93 +288,102 @@ def test_show_non_existent(self): # Verify cm is triggered with default parameters parsed_args = self.check_parser(self.cmd, arglist, verifylist) + find_mock_result = exceptions.CommandError('Resource Not Found') self.client.find_gateway = ( - fakes.FakeNatGateway.find_gateway( - self._data, 'unexist_nat_gateway')) + mock.Mock(side_effect=find_mock_result) + ) # Trigger the action try: self.cmd.take_action(parsed_args) - self.fail('CommandError should be raised.') except Exception as e: - self.assertEqual('404 Not Found', str(e)) + self.assertEqual('Resource Not Found', str(e)) self.client.find_gateway.assert_called_with('unexist_nat_gateway') class TestDeleteNatGateway(fakes.TestNat): - _data = fakes.FakeNatGateway.create_one() + _data = fakes.FakeNatGateway.create_multiple(2) def setUp(self): super(TestDeleteNatGateway, self).setUp() - self.cmd = gateway.DeleteNatGateway(self.app, None) - - self.client.find_gateway = ( - fakes.FakeNatGateway.find_gateway(self._data, self._data.id)) self.client.delete_gateway = mock.Mock(return_value=None) - def test_delete_by_id(self): + # Get the command object to test + self.cmd = gateway.DeleteNatGateway(self.app, None) + + def test_delete(self): arglist = [ - self._data.id, + self._data[0].name, ] verifylist = [ - ('gateway', self._data.id), + ('gateway', [self._data[0].name]), ] # Verify cm is triggered with default parameters parsed_args = self.check_parser(self.cmd, arglist, verifylist) - # Trigger the action - self.cmd.take_action(parsed_args) + self.client.find_gateway = ( + mock.Mock(return_value=self._data[0]) + ) - self.client.find_gateway.assert_called_with(self._data.id) + # Trigger the action + result = self.cmd.take_action(parsed_args) + self.client.delete_gateway.assert_called_with(self._data[0].id) + self.assertIsNone(result) - self.client.delete_gateway.assert_called_with(self._data.id) + def test_multiple_delete(self): + arglist = [] - def test_delete_by_name(self): - arglist = [ - self._data.name, - ] + for nat_gw in self._data: + arglist.append(nat_gw.name) verifylist = [ - ('gateway', self._data.name), + ('gateway', arglist), ] # Verify cm is triggered with default parameters parsed_args = self.check_parser(self.cmd, arglist, verifylist) + find_mock_result = self._data self.client.find_gateway = ( - fakes.FakeNatGateway.find_gateway(self._data, self._data.name)) + mock.Mock(side_effect=find_mock_result) + ) # Trigger the action - self.cmd.take_action(parsed_args) + result = self.cmd.take_action(parsed_args) - self.client.find_gateway.assert_called_with(self._data.name) + calls = [] + for nat_gw in self._data: + calls.append(call(nat_gw.id)) + self.client.delete_gateway.assert_has_calls(calls) + self.assertIsNone(result) - self.client.delete_gateway.assert_called_with(self._data.id) - - def test_delete_non_existent(self): + def test_multiple_delete_with_exception(self): arglist = [ + self._data[0].name, 'unexist_nat_gateway', ] - verifylist = [ - ('gateway', 'unexist_nat_gateway'), + ('gateway', arglist), ] # Verify cm is triggered with default parameters parsed_args = self.check_parser(self.cmd, arglist, verifylist) + find_mock_result = [self._data[0], exceptions.CommandError] self.client.find_gateway = ( - fakes.FakeNatGateway.find_gateway( - self._data, 'unexist_nat_gateway')) + mock.Mock(side_effect=find_mock_result) + ) # Trigger the action try: self.cmd.take_action(parsed_args) - self.fail('CommandError should be raised.') except Exception as e: - self.assertEqual('404 Not Found', str(e)) - self.client.find_gateway.assert_called_with('unexist_nat_gateway') + self.assertEqual('1 of 2 NAT Gateway(s) failed to delete.', str(e)) + + self.client.find_gateway.assert_any_call(self._data[0].name) + self.client.find_gateway.assert_any_call('unexist_nat_gateway') + self.client.delete_gateway.assert_called_once_with(self._data[0].id) diff --git a/otcextensions/tests/unit/osclient/nat/v2/test_snat.py b/otcextensions/tests/unit/osclient/nat/v2/test_snat.py index 23c861630..0a046eaa3 100644 --- a/otcextensions/tests/unit/osclient/nat/v2/test_snat.py +++ b/otcextensions/tests/unit/osclient/nat/v2/test_snat.py @@ -11,10 +11,15 @@ # under the License. # import mock +from unittest.mock import call + +from osc_lib import exceptions from otcextensions.osclient.nat.v2 import snat from otcextensions.tests.unit.osclient.nat.v2 import fakes +from openstackclient.tests.unit import utils as tests_utils + class TestListSnatRules(fakes.TestNat): @@ -213,13 +218,22 @@ def setUp(self): self.client.get_snat_rule = mock.Mock(return_value=self._data) + def test_show_no_options(self): + arglist = [] + verifylist = [] + + # Testing that a call without the required argument will fail and + # throw a "ParserExecption" + self.assertRaises(tests_utils.ParserException, + self.check_parser, self.cmd, arglist, verifylist) + def test_show(self): arglist = [ - 'test_snat_rule_id', + self._data.id, ] verifylist = [ - ('snat', 'test_snat_rule_id'), + ('snat', self._data.id), ] # Verify cm is triggered with default parameters @@ -227,7 +241,7 @@ def test_show(self): # Trigger the action columns, data = self.cmd.take_action(parsed_args) - self.client.get_snat_rule.assert_called_with('test_snat_rule_id') + self.client.get_snat_rule.assert_called_with(self._data.id) self.assertEqual(self.columns, columns) self.assertEqual(self.data, data) @@ -238,77 +252,108 @@ def test_show_non_existent(self): ] verifylist = [ - ('snat', 'unexist_snat_rule_id'), + ('snat', arglist[0]), ] # Verify cm is triggered with default parameters parsed_args = self.check_parser(self.cmd, arglist, verifylist) + find_mock_result = exceptions.CommandError('Resource Not Found') self.client.get_snat_rule = ( - fakes.FakeSnatRule.get_snat_rule( - self._data, 'unexist_snat_rule_id')) + mock.Mock(side_effect=find_mock_result) + ) # Trigger the action try: self.cmd.take_action(parsed_args) - self.fail('CommandError should be raised.') except Exception as e: - self.assertEqual('404 Not Found', str(e)) - self.client.get_snat_rule.assert_called_with('unexist_snat_rule_id') + self.assertEqual('Resource Not Found', str(e)) + self.client.get_snat_rule.assert_called_with(arglist[0]) class TestDeleteSnatRule(fakes.TestNat): - _data = fakes.FakeSnatRule.create_one() + _data = fakes.FakeSnatRule.create_multiple(2) def setUp(self): super(TestDeleteSnatRule, self).setUp() - self.client.get_snat_rule = ( - fakes.FakeSnatRule.get_snat_rule(self._data, self._data.id)) self.client.delete_snat_rule = mock.Mock(return_value=None) self.cmd = snat.DeleteSnatRule(self.app, None) def test_delete(self): arglist = [ - self._data.id, + self._data[0].id, ] verifylist = [ - ('snat', self._data.id), + ('snat', arglist), ] # Verify cm is triggered with default parameters parsed_args = self.check_parser(self.cmd, arglist, verifylist) + self.client.get_snat_rule = ( + mock.Mock(return_value=self._data[0]) + ) + # Trigger the action - self.cmd.take_action(parsed_args) + result = self.cmd.take_action(parsed_args) + self.client.get_snat_rule.assert_called_with(self._data[0].id) + self.client.delete_snat_rule.assert_called_with(self._data[0].id) + self.assertIsNone(result) - self.client.get_snat_rule.assert_called_with(self._data.id) + def test_multiple_delete(self): + arglist = [] + + for snat_rule in self._data: + arglist.append(snat_rule.id) - self.client.delete_snat_rule.assert_called_with(self._data.id) + verifylist = [ + ('snat', arglist), + ] - def test_delete_non_existent(self): + # Verify cm is triggered with default parameters + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + find_mock_result = self._data + self.client.get_snat_rule = ( + mock.Mock(side_effect=find_mock_result) + ) + + # Trigger the action + result = self.cmd.take_action(parsed_args) + + calls = [] + for snat_rule in self._data: + calls.append(call(snat_rule.id)) + self.client.delete_snat_rule.assert_has_calls(calls) + self.assertIsNone(result) + + def test_multiple_delete_with_exception(self): arglist = [ + self._data[0].id, 'unexist_snat_rule_id', ] - verifylist = [ - ('snat', 'unexist_snat_rule_id'), + ('snat', arglist), ] # Verify cm is triggered with default parameters parsed_args = self.check_parser(self.cmd, arglist, verifylist) + find_mock_result = [self._data[0], exceptions.CommandError] self.client.get_snat_rule = ( - fakes.FakeSnatRule.get_snat_rule( - self._data, 'unexist_snat_rule_id')) + mock.Mock(side_effect=find_mock_result) + ) # Trigger the action try: self.cmd.take_action(parsed_args) - self.fail('CommandError should be raised.') except Exception as e: - self.assertEqual('404 Not Found', str(e)) - self.client.get_snat_rule.assert_called_with('unexist_snat_rule_id') + self.assertEqual('1 of 2 SNAT Rule(s) failed to delete.', str(e)) + + self.client.get_snat_rule.assert_any_call(arglist[0]) + self.client.get_snat_rule.assert_any_call(arglist[1]) + self.client.delete_snat_rule.assert_called_once_with(arglist[0]) From 5b791a7277b279eb5df0594eada4405e85614dab Mon Sep 17 00:00:00 2001 From: Vineet Pruthi Date: Mon, 6 Apr 2020 03:53:24 +0000 Subject: [PATCH 67/73] Fixed resource cleanup issue --- otcextensions/tests/functional/osclient/nat/v2/common.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/otcextensions/tests/functional/osclient/nat/v2/common.py b/otcextensions/tests/functional/osclient/nat/v2/common.py index 0336922da..8a943a617 100644 --- a/otcextensions/tests/functional/osclient/nat/v2/common.py +++ b/otcextensions/tests/functional/osclient/nat/v2/common.py @@ -41,7 +41,7 @@ def setUp(self): def create_nat_gateway(self, name=None): self._initialize_network() - name = name or self.SUBNET_NAME + name = name or self.NAT_NAME json_output = json.loads(self.openstack( 'nat gateway create {name}' ' --router-id {router_id}' @@ -144,6 +144,9 @@ def _initialize_network(self): self.FLOATING_IP_ID = floating_ip['id'] def _denitialize_network(self): + self.openstack( + 'floating ip delete ' + self.FLOATING_IP_ID + ) self.openstack( 'router remove subnet {router} ' '{subnet} '.format( @@ -160,6 +163,3 @@ def _denitialize_network(self): self.openstack( 'router delete ' + self.ROUTER_NAME ) - self.openstack( - 'floating ip delete ' + self.FLOATING_IP_ID - ) From ff9947365f88e2c5754c2f1af6cd0ae3daae3efd Mon Sep 17 00:00:00 2001 From: Vineet Pruthi Date: Mon, 6 Apr 2020 07:10:24 +0000 Subject: [PATCH 68/73] checkout doc/source/cli/index.rst with origin/master --- doc/source/cli/index.rst | 51 +++++++++++++++++++++++++++------------- 1 file changed, 35 insertions(+), 16 deletions(-) diff --git a/doc/source/cli/index.rst b/doc/source/cli/index.rst index 524564ba6..c4d31c1f4 100644 --- a/doc/source/cli/index.rst +++ b/doc/source/cli/index.rst @@ -1,19 +1,38 @@ -OpenStackClient CLI Usage -========================= +OpenStack Client (CLI) +====================== + +The OpenStack Client is a self-contained OpenStack project providing a +command line interface to the most important cloud functions. For most +of the API calls an equivalent CLI command is available under a shared +command invoked as ``openstack``. An example is ``openstack server +list``. For reference see the documentation of the OpenStack Client +(OSC). + +The OTC Extensions don't re-implement the CLI tool, but augment it +automatically. If you have installed OTC Extensions and OpenStack +Client, the latter understands many extra commands: + +.. code-block:: bash + + openstack --help | grep -c otcextensions + 164 + +For details of the available commands, check the detailed CLI +documentation of these services: .. toctree:: - :maxdepth: 2 + :maxdepth: 1 - anti_ddos.rst - auto_scaling.rst - cce_v2.rst - cts.rst - dcs.rst - deh.rst - dms.rst - dns.rst - rds.rst - kms.rst - load_balancer.rst - obs.rst - volume_backup.rst + anti_ddos + auto_scaling + cce_v2 + cts + dcs + deh + dms + dns + kms + load_balancer + obs + rds + volume_backup From 8d187c4d05e2f52d0b0c566db6162cb78e0437ff Mon Sep 17 00:00:00 2001 From: Vineet Pruthi Date: Tue, 7 Apr 2020 08:18:03 +0000 Subject: [PATCH 69/73] Adding NAT doc --- doc/source/sdk/proxies/index.rst | 3 +- doc/source/sdk/proxies/nat.rst | 45 +++++++++++++++++++ doc/source/sdk/resources/index.rst | 1 + doc/source/sdk/resources/nat/index.rst | 9 ++++ doc/source/sdk/resources/nat/v2/dnat.rst | 13 ++++++ doc/source/sdk/resources/nat/v2/gateway.rst | 13 ++++++ doc/source/sdk/resources/nat/v2/snat.rst | 13 ++++++ .../tests/unit/osclient/nat/v2/fakes.py | 21 +++++---- 8 files changed, 109 insertions(+), 9 deletions(-) create mode 100644 doc/source/sdk/proxies/nat.rst create mode 100644 doc/source/sdk/resources/nat/index.rst create mode 100644 doc/source/sdk/resources/nat/v2/dnat.rst create mode 100644 doc/source/sdk/resources/nat/v2/gateway.rst create mode 100644 doc/source/sdk/resources/nat/v2/snat.rst diff --git a/doc/source/sdk/proxies/index.rst b/doc/source/sdk/proxies/index.rst index e83847d81..c5f6a8d11 100644 --- a/doc/source/sdk/proxies/index.rst +++ b/doc/source/sdk/proxies/index.rst @@ -14,10 +14,11 @@ Service Proxies Distributed Message Service (DMS) Domain Name Server Service (DNS) Key Management Service (KMS) + Network Address Translation (NAT) Object Block Storage (OBS) - Volume Backup Service (VBS) Relational Database Service RDS V1 (RDSv1) Relational Database Service RDS V3 (RDS) + Volume Backup Service (VBS) .. _service-proxies: diff --git a/doc/source/sdk/proxies/nat.rst b/doc/source/sdk/proxies/nat.rst new file mode 100644 index 000000000..481c3ec9f --- /dev/null +++ b/doc/source/sdk/proxies/nat.rst @@ -0,0 +1,45 @@ +NAT API +======= + +.. automodule:: otcextensions.sdk.nat.v2._proxy + +The Network Address Translation Class +------------------------------------- + +The nat high-level interface is available through the ``nat`` +member of a :class:`~openstack.connection.Connection` object. The +``nat`` member will only be added if the +``otcextensions.sdk.register_otc_extensions(conn)`` method is called. + +Gateway Operations +^^^^^^^^^^^^^^^^^^ + +.. autoclass:: otcextensions.sdk.nat.v2._proxy.Proxy + + .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.gateways + .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.create_gateway + .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.find_gateway + .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.update_gateway + .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.delete_gateway + + +SNAT Rule Operations +^^^^^^^^^^^^^^^^^^^^ + +.. autoclass:: otcextensions.sdk.nat.v2._proxy.Proxy + + .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.snat_rules + .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.create_snat_rule + .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.get_snat_rule + .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.delete_snat_rule + + +DNAT Rule Operations +^^^^^^^^^^^^^^^^^^^^ + +.. autoclass:: otcextensions.sdk.nat.v2._proxy.Proxy + + .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.dnat_rules + .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.create_dnat_rule + .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.get_dnat_rule + .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.delete_dnat_rule diff --git a/doc/source/sdk/resources/index.rst b/doc/source/sdk/resources/index.rst index 8987ad415..a8fb45e4b 100644 --- a/doc/source/sdk/resources/index.rst +++ b/doc/source/sdk/resources/index.rst @@ -16,6 +16,7 @@ Open Telekom Cloud Resources Distributed Message Service (DMS) Domain Name Service (DNS) Key Management Service (KMS) + Network Address Translation (NAT) Object Block Storage (OBS) Relational Database Service (RDS) diff --git a/doc/source/sdk/resources/nat/index.rst b/doc/source/sdk/resources/nat/index.rst new file mode 100644 index 000000000..506981865 --- /dev/null +++ b/doc/source/sdk/resources/nat/index.rst @@ -0,0 +1,9 @@ +DMS Resources +============= + +.. toctree:: + :maxdepth: 1 + + v2/gateway + v2/snat + v2/dnat diff --git a/doc/source/sdk/resources/nat/v2/dnat.rst b/doc/source/sdk/resources/nat/v2/dnat.rst new file mode 100644 index 000000000..8fcb3cf4f --- /dev/null +++ b/doc/source/sdk/resources/nat/v2/dnat.rst @@ -0,0 +1,13 @@ +otcextensions.sdk.nat.v2.dnat +============================= + +.. automodule:: otcextensions.sdk.nat.v2.dnat + +The DNAT Rule Class +-------------------- + +The ``Dnat`` class inherits from +:class:`~otcextensions.sdk.sdk_resource.Resource`. + +.. autoclass:: otcextensions.sdk.nat.v2.dnat.Dnat + :members: diff --git a/doc/source/sdk/resources/nat/v2/gateway.rst b/doc/source/sdk/resources/nat/v2/gateway.rst new file mode 100644 index 000000000..1fea7908d --- /dev/null +++ b/doc/source/sdk/resources/nat/v2/gateway.rst @@ -0,0 +1,13 @@ +otcextensions.sdk.nat.v2.gateway +================================ + +.. automodule:: otcextensions.sdk.nat.v2.gateway + +The NAT Gateway Class +---------------------- + +The ``Gateway`` class inherits from +:class:`~otcextensions.sdk.sdk_resource.Resource`. + +.. autoclass:: otcextensions.sdk.nat.v2.gateway.Gateway + :members: diff --git a/doc/source/sdk/resources/nat/v2/snat.rst b/doc/source/sdk/resources/nat/v2/snat.rst new file mode 100644 index 000000000..6dd62e650 --- /dev/null +++ b/doc/source/sdk/resources/nat/v2/snat.rst @@ -0,0 +1,13 @@ +otcextensions.sdk.nat.v2.snat +============================= + +.. automodule:: otcextensions.sdk.nat.v2.snat + +The SNAT Rule Class +-------------------- + +The ``Snat`` class inherits from +:class:`~otcextensions.sdk.sdk_resource.Resource`. + +.. autoclass:: otcextensions.sdk.nat.v2.snat.Snat + :members: diff --git a/otcextensions/tests/unit/osclient/nat/v2/fakes.py b/otcextensions/tests/unit/osclient/nat/v2/fakes.py index 1291c36bb..435ebc0e7 100644 --- a/otcextensions/tests/unit/osclient/nat/v2/fakes.py +++ b/otcextensions/tests/unit/osclient/nat/v2/fakes.py @@ -46,13 +46,13 @@ def setUp(self): class FakeNatGateway(test_base.Fake): - """Fake one or more datastore versions.""" + """Fake one or more Nat Gateways.""" @classmethod def generate(cls): - """Create a fake datastore. + """Create a fake NAT Gateway. :return: - A FakeResource object, with id, name, metadata, and so on + A FakeResource object, with id, name and so on """ # Set default attributes. object_info = { @@ -72,15 +72,14 @@ def generate(cls): class FakeSnatRule(test_base.Fake): - """Fake one or more Instance.""" + """Fake one or more SNAT Rule.""" @classmethod def generate(cls): - """Create a fake Configuration. + """Create a fake SNAT Rule. :return: - A FakeResource object, with id, name, metadata, and so on + A FakeResource object, with id, status and so on """ - # Set default attributes. object_info = { "id": "id-" + uuid.uuid4().hex, @@ -100,9 +99,15 @@ def generate(cls): class FakeDnatRule(test_base.Fake): - """Fake one or more Backup""" + """Fake one or more DNAT Rule""" @classmethod def generate(cls): + """Create a fake DNAT Rule. + + :return: + A FakeResource object, with id, status and so on + """ + # Set default attributes. object_info = { "id": "id-" + uuid.uuid4().hex, "floating_ip_id": "eip-id-" + uuid.uuid4().hex, From 90d66c103ff0381b1b32bdc9b4a3615bcab1555f Mon Sep 17 00:00:00 2001 From: Vineet Pruthi Date: Tue, 7 Apr 2020 08:23:36 +0000 Subject: [PATCH 70/73] Minor correction --- doc/source/sdk/resources/nat/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/sdk/resources/nat/index.rst b/doc/source/sdk/resources/nat/index.rst index 506981865..712e949da 100644 --- a/doc/source/sdk/resources/nat/index.rst +++ b/doc/source/sdk/resources/nat/index.rst @@ -1,4 +1,4 @@ -DMS Resources +NAT Resources ============= .. toctree:: From 395fd838a0f00c6abfadbbbb43a72773eb302cd2 Mon Sep 17 00:00:00 2001 From: Vineet Pruthi Date: Mon, 13 Apr 2020 02:01:03 +0000 Subject: [PATCH 71/73] Updated functional Tests --- .../v2/{test_dnat_rule.py => test_dnat.py} | 7 ++- .../{test_nat_gateway.py => test_gateway.py} | 7 ++- .../v2/{test_snat_rule.py => test_snat.py} | 9 ++-- .../tests/functional/sdk/nat/__init__.py | 0 .../tests/functional/sdk/nat/v2/__init__.py | 0 .../tests/functional/sdk/nat/v2/test_dnat.py | 48 +++++++++++++++++++ .../functional/sdk/nat/v2/test_gateway.py | 44 +++++++++++++++++ .../functional/sdk/nat/v2/test_service.py | 24 ++++++++++ .../tests/functional/sdk/nat/v2/test_snat.py | 46 ++++++++++++++++++ 9 files changed, 172 insertions(+), 13 deletions(-) rename otcextensions/tests/functional/osclient/nat/v2/{test_dnat_rule.py => test_dnat.py} (95%) rename otcextensions/tests/functional/osclient/nat/v2/{test_nat_gateway.py => test_gateway.py} (96%) rename otcextensions/tests/functional/osclient/nat/v2/{test_snat_rule.py => test_snat.py} (94%) create mode 100644 otcextensions/tests/functional/sdk/nat/__init__.py create mode 100644 otcextensions/tests/functional/sdk/nat/v2/__init__.py create mode 100644 otcextensions/tests/functional/sdk/nat/v2/test_dnat.py create mode 100644 otcextensions/tests/functional/sdk/nat/v2/test_gateway.py create mode 100644 otcextensions/tests/functional/sdk/nat/v2/test_service.py create mode 100644 otcextensions/tests/functional/sdk/nat/v2/test_snat.py diff --git a/otcextensions/tests/functional/osclient/nat/v2/test_dnat_rule.py b/otcextensions/tests/functional/osclient/nat/v2/test_dnat.py similarity index 95% rename from otcextensions/tests/functional/osclient/nat/v2/test_dnat_rule.py rename to otcextensions/tests/functional/osclient/nat/v2/test_dnat.py index 15cc511ec..0450c9120 100644 --- a/otcextensions/tests/functional/osclient/nat/v2/test_dnat_rule.py +++ b/otcextensions/tests/functional/osclient/nat/v2/test_dnat.py @@ -15,12 +15,11 @@ from otcextensions.tests.functional.osclient.nat.v2 import common -class TestDnatRule(common.NatTestCase): +class TestDnat(common.NatTestCase): """Functional Tests for NAT Gateway""" - @classmethod - def setUpClass(cls): - super(TestDnatRule, cls).setUpClass() + def setUp(self): + super(TestDnat, self).setUp() def test_nat_dnat_rule_list(self): json_output = json.loads(self.openstack( diff --git a/otcextensions/tests/functional/osclient/nat/v2/test_nat_gateway.py b/otcextensions/tests/functional/osclient/nat/v2/test_gateway.py similarity index 96% rename from otcextensions/tests/functional/osclient/nat/v2/test_nat_gateway.py rename to otcextensions/tests/functional/osclient/nat/v2/test_gateway.py index 5450a131a..aef96de1d 100644 --- a/otcextensions/tests/functional/osclient/nat/v2/test_nat_gateway.py +++ b/otcextensions/tests/functional/osclient/nat/v2/test_gateway.py @@ -15,12 +15,11 @@ from otcextensions.tests.functional.osclient.nat.v2 import common -class TestNatGateway(common.NatTestCase): +class TestGateway(common.NatTestCase): """Functional Tests for NAT Gateway""" - @classmethod - def setUpClass(cls): - super(TestNatGateway, cls).setUpClass() + def setUp(self): + super(TestGateway, self).setUp() def test_nat_gateway_list(self): json_output = json.loads(self.openstack( diff --git a/otcextensions/tests/functional/osclient/nat/v2/test_snat_rule.py b/otcextensions/tests/functional/osclient/nat/v2/test_snat.py similarity index 94% rename from otcextensions/tests/functional/osclient/nat/v2/test_snat_rule.py rename to otcextensions/tests/functional/osclient/nat/v2/test_snat.py index f396b45ad..07d8a5f97 100644 --- a/otcextensions/tests/functional/osclient/nat/v2/test_snat_rule.py +++ b/otcextensions/tests/functional/osclient/nat/v2/test_snat.py @@ -15,12 +15,11 @@ from otcextensions.tests.functional.osclient.nat.v2 import common -class TestSnatRule(common.NatTestCase): +class TestSnat(common.NatTestCase): """Functional Tests for NAT Gateway""" - @classmethod - def setUpClass(cls): - super(TestSnatRule, cls).setUpClass() + def setUp(self): + super(TestSnat, self).setUp() def test_snat_rule_list(self): json_output = json.loads(self.openstack( @@ -45,7 +44,7 @@ def test_snat_rule_list_filters(self): )) self.assertIsNotNone(json_output) - def test_nat_snat_rule_create(self): + def test_nat_snat_rule(self): json_output = self.create_snat_rule() self.addCleanup(self.delete_snat_rule) snat_rule_id = json_output['id'] diff --git a/otcextensions/tests/functional/sdk/nat/__init__.py b/otcextensions/tests/functional/sdk/nat/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/otcextensions/tests/functional/sdk/nat/v2/__init__.py b/otcextensions/tests/functional/sdk/nat/v2/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/otcextensions/tests/functional/sdk/nat/v2/test_dnat.py b/otcextensions/tests/functional/sdk/nat/v2/test_dnat.py new file mode 100644 index 000000000..57eab032c --- /dev/null +++ b/otcextensions/tests/functional/sdk/nat/v2/test_dnat.py @@ -0,0 +1,48 @@ +# 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 openstack +from otcextensions.tests.functional import base +from datetime import datetime + +_logger = openstack._log.setup_logging('openstack') + + +class TestDnat(base.BaseFunctionalTest): + CURR_TIME = datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f") + + def setUp(self): + super(TestDnat, self).setUp() + openstack.enable_logging(debug=True, http_debug=True) + + def test_list(self): + gateways = list(self.conn.nat.dnat_rules()) + self.assertGreaterEqual(len(gateways), 0) + + def test_list_filters(self): + attrs = { + 'limit': 1, + 'id': '2', + 'project_id': '3', + 'port_id': '4', + 'private_ip': '5', + 'internal_service_port': '6', + 'floating_ip_id': '7', + 'floating_ip_address': '8', + 'external_service_port': '9', + 'nat_gateway_id': '11', + 'protocol': 'tcp', + 'status': 'active', + 'admin_state_up': True, + 'created_at': self.CURR_TIME + } + gateways = list(self.conn.nat.dnat_rules(**attrs)) + self.assertGreaterEqual(len(gateways), 0) diff --git a/otcextensions/tests/functional/sdk/nat/v2/test_gateway.py b/otcextensions/tests/functional/sdk/nat/v2/test_gateway.py new file mode 100644 index 000000000..25583aeda --- /dev/null +++ b/otcextensions/tests/functional/sdk/nat/v2/test_gateway.py @@ -0,0 +1,44 @@ +# 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 openstack +from otcextensions.tests.functional import base +from datetime import datetime + +_logger = openstack._log.setup_logging('openstack') + + +class TestGateway(base.BaseFunctionalTest): + CURR_TIME = datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f") + + def setUp(self): + super(TestGateway, self).setUp() + openstack.enable_logging(debug=True, http_debug=True) + + def test_list(self): + gateways = list(self.conn.nat.gateways()) + self.assertGreaterEqual(len(gateways), 0) + + def test_list_filters(self): + attrs = { + 'limit': 1, + 'id': '2', + 'name': '3', + 'spec': '4', + 'router_id': '5', + 'internal_network_id': '6', + 'project_id': '7', + 'status': 'active', + 'admin_state_up': True, + 'created_at': self.CURR_TIME + } + gateways = list(self.conn.nat.gateways(**attrs)) + self.assertGreaterEqual(len(gateways), 0) diff --git a/otcextensions/tests/functional/sdk/nat/v2/test_service.py b/otcextensions/tests/functional/sdk/nat/v2/test_service.py new file mode 100644 index 000000000..3dd333c81 --- /dev/null +++ b/otcextensions/tests/functional/sdk/nat/v2/test_service.py @@ -0,0 +1,24 @@ +# 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. +from openstack import _log + +from otcextensions.tests.functional import base + +_logger = _log.setup_logging('openstack') + + +class TestService(base.BaseFunctionalTest): + + def test_initialize(self): + client = self.conn.nat + + self.assertIsNotNone(client) diff --git a/otcextensions/tests/functional/sdk/nat/v2/test_snat.py b/otcextensions/tests/functional/sdk/nat/v2/test_snat.py new file mode 100644 index 000000000..f7629a8bc --- /dev/null +++ b/otcextensions/tests/functional/sdk/nat/v2/test_snat.py @@ -0,0 +1,46 @@ +# 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 openstack +from otcextensions.tests.functional import base +from datetime import datetime + +_logger = openstack._log.setup_logging('openstack') + + +class TestSnat(base.BaseFunctionalTest): + CURR_TIME = datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f") + + def setUp(self): + super(TestSnat, self).setUp() + openstack.enable_logging(debug=True, http_debug=True) + + def test_list(self): + gateways = list(self.conn.nat.snat_rules()) + self.assertGreaterEqual(len(gateways), 0) + + def test_list_filters(self): + attrs = { + 'limit': 1, + 'id': '2', + 'project_id': '3', + 'nat_gateway_id': '4', + 'network_id': '5', + 'cidr': '6', + 'source_type': '7', + 'floating_ip_id': '8', + 'floating_ip_address': '9', + 'status': 'active', + 'admin_state_up': True, + 'created_at': self.CURR_TIME + } + gateways = list(self.conn.nat.snat_rules(**attrs)) + self.assertGreaterEqual(len(gateways), 0) From ba9737128bddfd071c09242ad759c7c36ffddc7a Mon Sep 17 00:00:00 2001 From: Artem Goncharov Date: Tue, 14 Apr 2020 12:32:58 +0200 Subject: [PATCH 72/73] fix for newer Sphinx --- doc/source/sdk/proxies/nat.rst | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/doc/source/sdk/proxies/nat.rst b/doc/source/sdk/proxies/nat.rst index 481c3ec9f..824b1d0b5 100644 --- a/doc/source/sdk/proxies/nat.rst +++ b/doc/source/sdk/proxies/nat.rst @@ -15,31 +15,20 @@ Gateway Operations ^^^^^^^^^^^^^^^^^^ .. autoclass:: otcextensions.sdk.nat.v2._proxy.Proxy - - .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.gateways - .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.create_gateway - .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.find_gateway - .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.update_gateway - .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.delete_gateway - + :noindex: + :members: gateways, find_gateway, + create_gateway, update_gateway, delete_gateway SNAT Rule Operations ^^^^^^^^^^^^^^^^^^^^ .. autoclass:: otcextensions.sdk.nat.v2._proxy.Proxy - - .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.snat_rules - .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.create_snat_rule - .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.get_snat_rule - .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.delete_snat_rule - + :noindex: + :members: snat_rules, get_snat_rule, create_snat_rule, delete_snat_rule DNAT Rule Operations ^^^^^^^^^^^^^^^^^^^^ .. autoclass:: otcextensions.sdk.nat.v2._proxy.Proxy - - .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.dnat_rules - .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.create_dnat_rule - .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.get_dnat_rule - .. automethod:: otcextensions.sdk.nat.v2._proxy.Proxy.delete_dnat_rule + :noindex: + :members: dnat_rules, get_dnat_rule, create_dnat_rule, delete_dnat_rule From 5e74b90c0fd8cbe42a6720a21038b9dc01bb1cd1 Mon Sep 17 00:00:00 2001 From: Artem Goncharov Date: Tue, 14 Apr 2020 12:59:43 +0200 Subject: [PATCH 73/73] do not append project_id in the nat service --- otcextensions/sdk/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/otcextensions/sdk/__init__.py b/otcextensions/sdk/__init__.py index 7bdb893d0..030d22517 100644 --- a/otcextensions/sdk/__init__.py +++ b/otcextensions/sdk/__init__.py @@ -115,7 +115,6 @@ }, 'nat': { 'service_type': 'nat', - 'append_project_id': True, }, 'obs': { 'service_type': 'obs',