From d44782bc089d6f3092cc2ee22ee4a13ea0c40ce9 Mon Sep 17 00:00:00 2001 From: Cao Xuan Hoang <hoangcx@vn.fujitsu.com> Date: Fri, 16 Sep 2016 14:31:26 +0700 Subject: [PATCH] Add filtering options to os subnet list command This patch adds the following filtering options: '--project' and '--project-domain', '--network', '--gateway', '--name', '--subnet-range' to the command. Change-Id: I575739486b9548492bd00f50130181b825534226 Partially-Implements: blueprint network-commands-options Closes-Bug: #1610883 --- doc/source/command-objects/subnet.rst | 31 +++++ openstackclient/network/v2/subnet.py | 51 +++++++- .../tests/unit/network/v2/test_subnet.py | 110 +++++++++++++++++- .../notes/bug-1610883-38929f6fc2eefc9a.yaml | 8 ++ 4 files changed, 198 insertions(+), 2 deletions(-) create mode 100644 releasenotes/notes/bug-1610883-38929f6fc2eefc9a.yaml diff --git a/doc/source/command-objects/subnet.rst b/doc/source/command-objects/subnet.rst index 4566d74d7b..d2ea6132c5 100644 --- a/doc/source/command-objects/subnet.rst +++ b/doc/source/command-objects/subnet.rst @@ -161,6 +161,11 @@ List subnets [--long] [--ip-version {4,6}] [--dhcp | --no-dhcp] + [--project <project> [--project-domain <project-domain>]] + [--network <network>] + [--gateway <gateway>] + [--name <name>] + [--subnet-range <subnet-range>] .. option:: --long @@ -186,6 +191,32 @@ List subnets Must be a valid device owner value for a network port (repeat option to list multiple service types) +.. option:: --project <project> + + List only subnets which belong to a given project (name or ID) in output + +.. option:: --project-domain <project-domain> + + Domain the project belongs to (name or ID). + This can be used in case collisions between project names exist. + +.. option:: --network <network> + + List only subnets which belong to a given network (name or ID) in output + +.. option:: --gateway <gateway> + + List only subnets of given gateway IP in output + +.. option:: --name <name> + + List only subnets of given name in output + +.. option:: --subnet-range <subnet-range> + + List only subnets of given subnet range (in CIDR notation) in output + e.g.: ``--subnet-range 10.10.0.0/16`` + subnet set ---------- diff --git a/openstackclient/network/v2/subnet.py b/openstackclient/network/v2/subnet.py index f1c7d15d55..8a3f229a2d 100644 --- a/openstackclient/network/v2/subnet.py +++ b/openstackclient/network/v2/subnet.py @@ -381,9 +381,41 @@ class ListSubnet(command.Lister): "Must be a valid device owner value for a network port " "(repeat option to list multiple service types)") ) + parser.add_argument( + '--project', + metavar='<project>', + help=_("List only subnets which belong to a given project " + "(name or ID) in output") + ) + identity_common.add_project_domain_option_to_parser(parser) + parser.add_argument( + '--network', + metavar='<network>', + help=_("List only subnets which belong to a given network " + "(name or ID) in output") + ) + parser.add_argument( + '--gateway', + metavar='<gateway>', + help=_("List only subnets of given gateway IP in output") + ) + parser.add_argument( + '--name', + metavar='<name>', + help=_("List only subnets of given name in output") + ) + parser.add_argument( + '--subnet-range', + metavar='<subnet-range>', + help=_("List only subnets of given subnet range " + "(in CIDR notation) in output " + "e.g.: --subnet-range 10.10.0.0/16") + ) return parser def take_action(self, parsed_args): + identity_client = self.app.client_manager.identity + network_client = self.app.client_manager.network filters = {} if parsed_args.ip_version: filters['ip_version'] = parsed_args.ip_version @@ -393,7 +425,24 @@ class ListSubnet(command.Lister): filters['enable_dhcp'] = False if parsed_args.service_types: filters['service_types'] = parsed_args.service_types - data = self.app.client_manager.network.subnets(**filters) + if parsed_args.project: + project_id = identity_common.find_project( + identity_client, + parsed_args.project, + parsed_args.project_domain, + ).id + filters['tenant_id'] = project_id + if parsed_args.network: + network_id = network_client.find_network(parsed_args.network, + ignore_missing=False).id + filters['network_id'] = network_id + if parsed_args.gateway: + filters['gateway_ip'] = parsed_args.gateway + if parsed_args.name: + filters['name'] = parsed_args.name + if parsed_args.subnet_range: + filters['cidr'] = parsed_args.subnet_range + data = network_client.subnets(**filters) headers = ('ID', 'Name', 'Network', 'Subnet') columns = ('id', 'name', 'network_id', 'cidr') diff --git a/openstackclient/tests/unit/network/v2/test_subnet.py b/openstackclient/tests/unit/network/v2/test_subnet.py index 6d7623443d..f09fe4faa0 100644 --- a/openstackclient/tests/unit/network/v2/test_subnet.py +++ b/openstackclient/tests/unit/network/v2/test_subnet.py @@ -646,7 +646,6 @@ class TestListSubnet(TestSubnet): ('service_types', ['network:router_gateway']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) - columns, data = self.cmd.take_action(parsed_args) filters = {'service_types': ['network:router_gateway']} @@ -654,6 +653,24 @@ class TestListSubnet(TestSubnet): self.assertEqual(self.columns, columns) self.assertEqual(self.data, list(data)) + def test_subnet_list_project(self): + project = identity_fakes_v3.FakeProject.create_one_project() + self.projects_mock.get.return_value = project + arglist = [ + '--project', project.id, + ] + verifylist = [ + ('project', project.id), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + columns, data = self.cmd.take_action(parsed_args) + filters = {'tenant_id': project.id} + + self.network.subnets.assert_called_once_with(**filters) + self.assertEqual(self.columns, columns) + self.assertEqual(self.data, list(data)) + def test_subnet_list_service_type_multiple(self): arglist = [ '--service-type', 'network:router_gateway', @@ -668,6 +685,97 @@ class TestListSubnet(TestSubnet): columns, data = self.cmd.take_action(parsed_args) filters = {'service_types': ['network:router_gateway', 'network:floatingip_agent_gateway']} + self.network.subnets.assert_called_once_with(**filters) + self.assertEqual(self.columns, columns) + self.assertEqual(self.data, list(data)) + + def test_subnet_list_project_domain(self): + project = identity_fakes_v3.FakeProject.create_one_project() + self.projects_mock.get.return_value = project + arglist = [ + '--project', project.id, + '--project-domain', project.domain_id, + ] + verifylist = [ + ('project', project.id), + ('project_domain', project.domain_id), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + columns, data = self.cmd.take_action(parsed_args) + filters = {'tenant_id': project.id} + + self.network.subnets.assert_called_once_with(**filters) + self.assertEqual(self.columns, columns) + self.assertEqual(self.data, list(data)) + + def test_subnet_list_network(self): + network = network_fakes.FakeNetwork.create_one_network() + self.network.find_network = mock.Mock(return_value=network) + arglist = [ + '--network', network.id, + ] + verifylist = [ + ('network', network.id), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + columns, data = self.cmd.take_action(parsed_args) + filters = {'network_id': network.id} + + self.network.subnets.assert_called_once_with(**filters) + self.assertEqual(self.columns, columns) + self.assertEqual(self.data, list(data)) + + def test_subnet_list_gateway(self): + subnet = network_fakes.FakeSubnet.create_one_subnet() + self.network.find_network = mock.Mock(return_value=subnet) + arglist = [ + '--gateway', subnet.gateway_ip, + ] + verifylist = [ + ('gateway', subnet.gateway_ip), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + columns, data = self.cmd.take_action(parsed_args) + filters = {'gateway_ip': subnet.gateway_ip} + + self.network.subnets.assert_called_once_with(**filters) + self.assertEqual(self.columns, columns) + self.assertEqual(self.data, list(data)) + + def test_subnet_list_name(self): + subnet = network_fakes.FakeSubnet.create_one_subnet() + self.network.find_network = mock.Mock(return_value=subnet) + arglist = [ + '--name', subnet.name, + ] + verifylist = [ + ('name', subnet.name), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + columns, data = self.cmd.take_action(parsed_args) + filters = {'name': subnet.name} + + self.network.subnets.assert_called_once_with(**filters) + self.assertEqual(self.columns, columns) + self.assertEqual(self.data, list(data)) + + def test_subnet_list_subnet_range(self): + subnet = network_fakes.FakeSubnet.create_one_subnet() + self.network.find_network = mock.Mock(return_value=subnet) + arglist = [ + '--subnet-range', subnet.cidr, + ] + verifylist = [ + ('subnet_range', subnet.cidr), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + columns, data = self.cmd.take_action(parsed_args) + filters = {'cidr': subnet.cidr} self.network.subnets.assert_called_once_with(**filters) self.assertEqual(self.columns, columns) diff --git a/releasenotes/notes/bug-1610883-38929f6fc2eefc9a.yaml b/releasenotes/notes/bug-1610883-38929f6fc2eefc9a.yaml new file mode 100644 index 0000000000..215c24f438 --- /dev/null +++ b/releasenotes/notes/bug-1610883-38929f6fc2eefc9a.yaml @@ -0,0 +1,8 @@ +--- +features: + - | + Make ``subnet list`` command supports listing up subnets with + some filtering options by adding ``--project`` and ``--project-domain``, + ``--network``, ``--gateway``,``--name``, ``--subnet-range`` + options to the command. + [Bug `1610883 <https://bugs.launchpad.net/bugs/1610883>`_]