diff --git a/doc/source/command-objects/address-scope.rst b/doc/source/command-objects/address-scope.rst index f37bc321a0..a2ab566c82 100644 --- a/doc/source/command-objects/address-scope.rst +++ b/doc/source/command-objects/address-scope.rst @@ -45,7 +45,7 @@ Create new address scope .. _address_scope_create-name: .. describe:: - New address scope name + New address scope name address scope delete -------------------- @@ -73,6 +73,36 @@ List address scopes os address scope list +address scope set +----------------- + +Set address scope properties + +.. program:: address scope set +.. code:: bash + + os address scope set + [--name ] + [--share | --no-share] + + +.. option:: --name + + Set address scope name + +.. option:: --share + + Share the address scope between projects + +.. option:: --no-share + + Do not share the address scope between projects + +.. _address_scope_set-address-scope: +.. describe:: + + Address scope to modify (name or ID) + address scope show ------------------ diff --git a/functional/tests/network/v2/test_address_scope.py b/functional/tests/network/v2/test_address_scope.py new file mode 100644 index 0000000000..8e25e46aa9 --- /dev/null +++ b/functional/tests/network/v2/test_address_scope.py @@ -0,0 +1,49 @@ +# 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 uuid + +from functional.common import test + + +class AddressScopeTests(test.TestCase): + """Functional tests for address scope. """ + NAME = uuid.uuid4().hex + HEADERS = ['Name'] + FIELDS = ['name'] + + @classmethod + def setUpClass(cls): + opts = cls.get_show_opts(cls.FIELDS) + raw_output = cls.openstack('address scope create ' + cls.NAME + opts) + cls.assertOutput(cls.NAME + "\n", raw_output) + + @classmethod + def tearDownClass(cls): + raw_output = cls.openstack('address scope delete ' + cls.NAME) + cls.assertOutput('', raw_output) + + def test_address_scope_list(self): + opts = self.get_list_opts(self.HEADERS) + raw_output = self.openstack('address scope list' + opts) + self.assertIn(self.NAME, raw_output) + + def test_address_scope_show(self): + opts = self.get_show_opts(self.FIELDS) + raw_output = self.openstack('address scope show ' + self.NAME + opts) + self.assertEqual(self.NAME + "\n", raw_output) + + def test_address_scope_set(self): + self.openstack('address scope set --share ' + self.NAME) + opts = self.get_show_opts(['shared']) + raw_output = self.openstack('address scope show ' + self.NAME + opts) + self.assertEqual("True\n", raw_output) diff --git a/openstackclient/network/v2/address_scope.py b/openstackclient/network/v2/address_scope.py index 86f39c3477..fac0849f6b 100644 --- a/openstackclient/network/v2/address_scope.py +++ b/openstackclient/network/v2/address_scope.py @@ -14,6 +14,7 @@ """Address scope action implementations""" from openstackclient.common import command +from openstackclient.common import exceptions from openstackclient.common import utils from openstackclient.i18n import _ from openstackclient.identity import common as identity_common @@ -142,6 +143,53 @@ class ListAddressScope(command.Lister): ) for s in data)) +class SetAddressScope(command.Command): + """Set address scope properties""" + + def get_parser(self, prog_name): + parser = super(SetAddressScope, self).get_parser(prog_name) + parser.add_argument( + 'address_scope', + metavar="", + help=_("Address scope to modify (name or ID)") + ) + parser.add_argument( + '--name', + metavar="", + help=_('Set address scope name') + ) + share_group = parser.add_mutually_exclusive_group() + share_group.add_argument( + '--share', + action='store_true', + help=_('Share the address scope between projects') + ) + share_group.add_argument( + '--no-share', + action='store_true', + help=_('Do not share the address scope between projects') + ) + + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.network + obj = client.find_address_scope( + parsed_args.address_scope, + ignore_missing=False) + attrs = {} + if parsed_args.name is not None: + attrs['name'] = parsed_args.name + if parsed_args.share: + attrs['shared'] = True + if parsed_args.no_share: + attrs['shared'] = False + if attrs == {}: + msg = "Nothing specified to be set." + raise exceptions.CommandError(msg) + client.update_address_scope(obj, **attrs) + + class ShowAddressScope(command.ShowOne): """Display address scope details""" diff --git a/openstackclient/tests/network/v2/test_address_scope.py b/openstackclient/tests/network/v2/test_address_scope.py index da658fefb1..ac94b489b1 100644 --- a/openstackclient/tests/network/v2/test_address_scope.py +++ b/openstackclient/tests/network/v2/test_address_scope.py @@ -14,6 +14,7 @@ import copy import mock +from openstackclient.common import exceptions from openstackclient.network.v2 import address_scope from openstackclient.tests import fakes from openstackclient.tests.identity.v3 import fakes as identity_fakes_v3 @@ -237,6 +238,72 @@ class TestListAddressScope(TestAddressScope): self.assertEqual(self.data, list(data)) +class TestSetAddressScope(TestAddressScope): + + # The address scope to set. + _address_scope = network_fakes.FakeAddressScope.create_one_address_scope() + + def setUp(self): + super(TestSetAddressScope, self).setUp() + self.network.update_address_scope = mock.Mock(return_value=None) + self.network.find_address_scope = mock.Mock( + return_value=self._address_scope) + + # Get the command object to test + self.cmd = address_scope.SetAddressScope(self.app, self.namespace) + + def test_set_nothing(self): + arglist = [self._address_scope.name, ] + verifylist = [ + ('address_scope', self._address_scope.name), + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + self.assertRaises(exceptions.CommandError, self.cmd.take_action, + parsed_args) + + def test_set_name_and_share(self): + arglist = [ + '--name', 'new_address_scope', + '--share', + self._address_scope.name, + ] + verifylist = [ + ('name', 'new_address_scope'), + ('share', True), + ('address_scope', self._address_scope.name), + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + result = self.cmd.take_action(parsed_args) + attrs = { + 'name': "new_address_scope", + 'shared': True, + } + self.network.update_address_scope.assert_called_with( + self._address_scope, **attrs) + self.assertIsNone(result) + + def test_set_no_share(self): + arglist = [ + '--no-share', + self._address_scope.name, + ] + verifylist = [ + ('no_share', True), + ('address_scope', self._address_scope.name), + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + result = self.cmd.take_action(parsed_args) + attrs = { + 'shared': False, + } + self.network.update_address_scope.assert_called_with( + self._address_scope, **attrs) + self.assertIsNone(result) + + class TestShowAddressScope(TestAddressScope): # The address scope to show. diff --git a/releasenotes/notes/bug-1566269-2572bca9157ca107.yaml b/releasenotes/notes/bug-1566269-2572bca9157ca107.yaml new file mode 100644 index 0000000000..9f34f67c7b --- /dev/null +++ b/releasenotes/notes/bug-1566269-2572bca9157ca107.yaml @@ -0,0 +1,5 @@ +--- +features: + - Add ``address scope create``,``address scope delete``,``address scope list``, + ``address scope set`` and ``address scope show`` commands. + [Bug `1566269 `_] diff --git a/setup.cfg b/setup.cfg index 3c8c829040..7c1d68c9f8 100644 --- a/setup.cfg +++ b/setup.cfg @@ -322,6 +322,7 @@ openstack.network.v2 = address_scope_create = openstackclient.network.v2.address_scope:CreateAddressScope address_scope_delete = openstackclient.network.v2.address_scope:DeleteAddressScope address_scope_list = openstackclient.network.v2.address_scope:ListAddressScope + address_scope_set = openstackclient.network.v2.address_scope:SetAddressScope address_scope_show = openstackclient.network.v2.address_scope:ShowAddressScope ip_floating_create = openstackclient.network.v2.floating_ip:CreateFloatingIP