Skip to content

Commit a29c973

Browse files
committed
Refactor security group rule delete to use SDK
Refactored the 'os security group rule delete' command to use the SDK when neutron is enabled, but continue to use the nova client when nova network is enabled. This patch set also introduces new FakeSecurityGroupRule classes for testing network and compute security group rules. And fixes were made to the network FakeSecurityGroup class. Change-Id: I8d0917925aa464e8255defae95a2a2adfb6cfb75 Partial-Bug: #1519512 Related-to: blueprint neutron-client
1 parent 624c39a commit a29c973

7 files changed

Lines changed: 266 additions & 33 deletions

File tree

openstackclient/compute/v2/security_group.py

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -169,24 +169,6 @@ def take_action(self, parsed_args):
169169
return zip(*sorted(six.iteritems(info)))
170170

171171

172-
class DeleteSecurityGroupRule(command.Command):
173-
"""Delete a security group rule"""
174-
175-
def get_parser(self, prog_name):
176-
parser = super(DeleteSecurityGroupRule, self).get_parser(prog_name)
177-
parser.add_argument(
178-
'rule',
179-
metavar='<rule>',
180-
help='Security group rule to delete (ID only)',
181-
)
182-
return parser
183-
184-
def take_action(self, parsed_args):
185-
186-
compute_client = self.app.client_manager.compute
187-
compute_client.security_group_rules.delete(parsed_args.rule)
188-
189-
190172
class ListSecurityGroup(command.Lister):
191173
"""List security groups"""
192174

openstackclient/network/common.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,13 @@
1919

2020
@six.add_metaclass(abc.ABCMeta)
2121
class NetworkAndComputeCommand(command.Command):
22-
"""Network and Compute Command"""
22+
"""Network and Compute Command
23+
24+
Command class for commands that support implementation via
25+
the network or compute endpoint. Such commands have different
26+
implementations for take_action() and may even have different
27+
arguments.
28+
"""
2329

2430
def take_action(self, parsed_args):
2531
if self.app.client_manager.is_network_endpoint_enabled():
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
2+
# not use this file except in compliance with the License. You may obtain
3+
# a copy of the License at
4+
#
5+
# http://www.apache.org/licenses/LICENSE-2.0
6+
#
7+
# Unless required by applicable law or agreed to in writing, software
8+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10+
# License for the specific language governing permissions and limitations
11+
# under the License.
12+
#
13+
14+
"""Security Group Rule action implementations"""
15+
16+
from openstackclient.network import common
17+
18+
19+
class DeleteSecurityGroupRule(common.NetworkAndComputeCommand):
20+
"""Delete a security group rule"""
21+
22+
def update_parser_common(self, parser):
23+
parser.add_argument(
24+
'rule',
25+
metavar='<rule>',
26+
help='Security group rule to delete (ID only)',
27+
)
28+
return parser
29+
30+
def take_action_network(self, client, parsed_args):
31+
obj = client.find_security_group_rule(parsed_args.rule)
32+
client.delete_security_group_rule(obj)
33+
34+
def take_action_compute(self, client, parsed_args):
35+
client.security_group_rules.delete(parsed_args.rule)

openstackclient/tests/compute/v2/fakes.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,68 @@ def create_hypervisors(attrs={}, count=2):
228228
return hypervisors
229229

230230

231+
class FakeSecurityGroupRule(object):
232+
"""Fake one or more security group rules."""
233+
234+
@staticmethod
235+
def create_one_security_group_rule(attrs={}, methods={}):
236+
"""Create a fake security group rule.
237+
238+
:param Dictionary attrs:
239+
A dictionary with all attributes
240+
:param Dictionary methods:
241+
A dictionary with all methods
242+
:return:
243+
A FakeResource object, with id, etc.
244+
"""
245+
# Set default attributes.
246+
security_group_rule_attrs = {
247+
'from_port': -1,
248+
'group': {},
249+
'id': 'security-group-rule-id-' + uuid.uuid4().hex,
250+
'ip_protocol': 'icmp',
251+
'ip_range': {'cidr': '0.0.0.0/0'},
252+
'parent_group_id': 'security-group-id-' + uuid.uuid4().hex,
253+
'to_port': -1,
254+
}
255+
256+
# Overwrite default attributes.
257+
security_group_rule_attrs.update(attrs)
258+
259+
# Set default methods.
260+
security_group_rule_methods = {}
261+
262+
# Overwrite default methods.
263+
security_group_rule_methods.update(methods)
264+
265+
security_group_rule = fakes.FakeResource(
266+
info=copy.deepcopy(security_group_rule_attrs),
267+
methods=copy.deepcopy(security_group_rule_methods),
268+
loaded=True)
269+
return security_group_rule
270+
271+
@staticmethod
272+
def create_security_group_rules(attrs={}, methods={}, count=2):
273+
"""Create multiple fake security group rules.
274+
275+
:param Dictionary attrs:
276+
A dictionary with all attributes
277+
:param Dictionary methods:
278+
A dictionary with all methods
279+
:param int count:
280+
The number of security group rules to fake
281+
:return:
282+
A list of FakeResource objects faking the security group rules
283+
"""
284+
security_group_rules = []
285+
for i in range(0, count):
286+
security_group_rules.append(
287+
FakeSecurityGroupRule.create_one_security_group_rule(
288+
attrs, methods))
289+
290+
return security_group_rules
291+
292+
231293
class FakeServer(object):
232294
"""Fake one or more compute servers."""
233295

openstackclient/tests/network/v2/fakes.py

Lines changed: 61 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -463,28 +463,76 @@ def create_security_groups(attrs={}, methods={}, count=2):
463463
security_groups = []
464464
for i in range(0, count):
465465
security_groups.append(
466-
FakeRouter.create_one_security_group(attrs, methods))
466+
FakeSecurityGroup.create_one_security_group(attrs, methods))
467467

468468
return security_groups
469469

470+
471+
class FakeSecurityGroupRule(object):
472+
"""Fake one or more security group rules."""
473+
470474
@staticmethod
471-
def get_security_groups(security_groups=None, count=2):
472-
"""Get an iterable MagicMock object with a list of faked security groups.
475+
def create_one_security_group_rule(attrs={}, methods={}):
476+
"""Create a fake security group rule.
477+
478+
:param Dictionary attrs:
479+
A dictionary with all attributes
480+
:param Dictionary methods:
481+
A dictionary with all methods
482+
:return:
483+
A FakeResource object, with id, name, etc.
484+
"""
485+
# Set default attributes.
486+
security_group_rule_attrs = {
487+
'description': 'security-group-rule-desc-' + uuid.uuid4().hex,
488+
'direction': 'ingress',
489+
'ethertype': 'IPv4',
490+
'id': 'security-group-rule-id-' + uuid.uuid4().hex,
491+
'name': 'security-group-rule-name-' + uuid.uuid4().hex,
492+
'port_range_max': None,
493+
'port_range_min': None,
494+
'protocol': None,
495+
'remote_group_id': 'remote-security-group-id-' + uuid.uuid4().hex,
496+
'remote_ip_prefix': None,
497+
'security_group_id': 'security-group-id-' + uuid.uuid4().hex,
498+
'tenant_id': 'project-id-' + uuid.uuid4().hex,
499+
}
500+
501+
# Overwrite default attributes.
502+
security_group_rule_attrs.update(attrs)
473503

474-
If security group list is provided, then initialize the Mock object
475-
with the list. Otherwise create one.
504+
# Set default methods.
505+
security_group_rule_methods = {}
506+
507+
# Overwrite default methods.
508+
security_group_rule_methods.update(methods)
509+
510+
security_group_rule = fakes.FakeResource(
511+
info=copy.deepcopy(security_group_rule_attrs),
512+
methods=copy.deepcopy(security_group_rule_methods),
513+
loaded=True)
514+
return security_group_rule
515+
516+
@staticmethod
517+
def create_security_group_rules(attrs={}, methods={}, count=2):
518+
"""Create multiple fake security group rules.
476519
477-
:param List security groups:
478-
A list of FakeResource objects faking security groups
520+
:param Dictionary attrs:
521+
A dictionary with all attributes
522+
:param Dictionary methods:
523+
A dictionary with all methods
479524
:param int count:
480-
The number of security groups to fake
525+
The number of security group rules to fake
481526
:return:
482-
An iterable Mock object with side_effect set to a list of faked
483-
security groups
527+
A list of FakeResource objects faking the security group rules
484528
"""
485-
if security_groups is None:
486-
security_groups = FakeRouter.create_security_groups(count)
487-
return mock.MagicMock(side_effect=security_groups)
529+
security_group_rules = []
530+
for i in range(0, count):
531+
security_group_rules.append(
532+
FakeSecurityGroupRule.create_one_security_group_rule(
533+
attrs, methods))
534+
535+
return security_group_rules
488536

489537

490538
class FakeSubnet(object):
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
2+
# not use this file except in compliance with the License. You may obtain
3+
# a copy of the License at
4+
#
5+
# http://www.apache.org/licenses/LICENSE-2.0
6+
#
7+
# Unless required by applicable law or agreed to in writing, software
8+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10+
# License for the specific language governing permissions and limitations
11+
# under the License.
12+
#
13+
14+
import mock
15+
16+
from openstackclient.network.v2 import security_group_rule
17+
from openstackclient.tests.compute.v2 import fakes as compute_fakes
18+
from openstackclient.tests.network.v2 import fakes as network_fakes
19+
20+
21+
class TestSecurityGroupRuleNetwork(network_fakes.TestNetworkV2):
22+
23+
def setUp(self):
24+
super(TestSecurityGroupRuleNetwork, self).setUp()
25+
26+
# Get a shortcut to the network client
27+
self.network = self.app.client_manager.network
28+
29+
30+
class TestSecurityGroupRuleCompute(compute_fakes.TestComputev2):
31+
32+
def setUp(self):
33+
super(TestSecurityGroupRuleCompute, self).setUp()
34+
35+
# Get a shortcut to the network client
36+
self.compute = self.app.client_manager.compute
37+
38+
39+
class TestDeleteSecurityGroupRuleNetwork(TestSecurityGroupRuleNetwork):
40+
41+
# The security group rule to be deleted.
42+
_security_group_rule = \
43+
network_fakes.FakeSecurityGroupRule.create_one_security_group_rule()
44+
45+
def setUp(self):
46+
super(TestDeleteSecurityGroupRuleNetwork, self).setUp()
47+
48+
self.network.delete_security_group_rule = mock.Mock(return_value=None)
49+
50+
self.network.find_security_group_rule = mock.Mock(
51+
return_value=self._security_group_rule)
52+
53+
# Get the command object to test
54+
self.cmd = security_group_rule.DeleteSecurityGroupRule(
55+
self.app, self.namespace)
56+
57+
def test_security_group_rule_delete(self):
58+
arglist = [
59+
self._security_group_rule.id,
60+
]
61+
verifylist = [
62+
('rule', self._security_group_rule.id),
63+
]
64+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
65+
66+
result = self.cmd.take_action(parsed_args)
67+
68+
self.network.delete_security_group_rule.assert_called_with(
69+
self._security_group_rule)
70+
self.assertEqual(None, result)
71+
72+
73+
class TestDeleteSecurityGroupRuleCompute(TestSecurityGroupRuleCompute):
74+
75+
# The security group rule to be deleted.
76+
_security_group_rule = \
77+
compute_fakes.FakeSecurityGroupRule.create_one_security_group_rule()
78+
79+
def setUp(self):
80+
super(TestDeleteSecurityGroupRuleCompute, self).setUp()
81+
82+
self.app.client_manager.network_endpoint_enabled = False
83+
84+
# Get the command object to test
85+
self.cmd = security_group_rule.DeleteSecurityGroupRule(self.app, None)
86+
87+
def test_security_group_rule_delete(self):
88+
arglist = [
89+
self._security_group_rule.id,
90+
]
91+
verifylist = [
92+
('rule', self._security_group_rule.id),
93+
]
94+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
95+
96+
result = self.cmd.take_action(parsed_args)
97+
98+
self.compute.security_group_rules.delete.assert_called_with(
99+
self._security_group_rule.id)
100+
self.assertEqual(None, result)

setup.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,6 @@ openstack.compute.v2 =
107107
security_group_set = openstackclient.compute.v2.security_group:SetSecurityGroup
108108
security_group_show = openstackclient.compute.v2.security_group:ShowSecurityGroup
109109
security_group_rule_create = openstackclient.compute.v2.security_group:CreateSecurityGroupRule
110-
security_group_rule_delete = openstackclient.compute.v2.security_group:DeleteSecurityGroupRule
111110
security_group_rule_list = openstackclient.compute.v2.security_group:ListSecurityGroupRule
112111

113112
server_add_security_group = openstackclient.compute.v2.server:AddServerSecurityGroup
@@ -340,6 +339,7 @@ openstack.network.v2 =
340339
router_set = openstackclient.network.v2.router:SetRouter
341340
router_show = openstackclient.network.v2.router:ShowRouter
342341
security_group_delete = openstackclient.network.v2.security_group:DeleteSecurityGroup
342+
security_group_rule_delete = openstackclient.network.v2.security_group_rule:DeleteSecurityGroupRule
343343
subnet_list = openstackclient.network.v2.subnet:ListSubnet
344344

345345
openstack.object_store.v1 =

0 commit comments

Comments
 (0)