Просмотр исходного кода

Add a method for checking equality of two security groups (ie __eq__). I believe the checks inherently cover the group rule as well but would appreciate a second opinion.

Enis Afgan 10 лет назад
Родитель
Сommit
7465e63f8a

+ 52 - 0
cloudbridge/providers/base.py

@@ -245,6 +245,58 @@ class BaseSecurityGroup(SecurityGroup):
         self._provider = provider
         self._security_group = security_group
 
+    def __eq__(self, other):
+        """
+        Check if all the defined rules match across both security groups.
+        """
+        if isinstance(other, SecurityGroup) and \
+           self._provider == other._provider:
+            eq = True
+            for rule in other.rules:
+                eq = eq and self.rule_exists(self.rules, rule.from_port,
+                                             rule.to_port, rule.ip_protocol,
+                                             rule.cidr_ip)
+            # Make sure other.rules does not contain a subset of self.rules
+            for rule in self.rules:
+                eq = eq and self.rule_exists(other.rules, rule.from_port,
+                                             rule.to_port, rule.ip_protocol,
+                                             rule.cidr_ip)
+            return eq
+        else:
+            return False
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def rule_exists(self, rules, from_port, to_port, ip_protocol, cidr_ip):
+        """
+        Check if an authorization rule with supplied parameters exists.
+
+        :type rules: list of :class:``.SecurityGroupRule`` SecurityGroupRule
+        :param rules: A list of rules to check against
+
+        :type ip_protocol: str
+        :param ip_protocol: Either ``tcp`` | ``udp`` | ``icmp``
+
+        :type from_port: int
+        :param from_port: The beginning port number
+
+        :type to_port: int
+        :param to_port: The ending port number
+
+        :type cidr_ip: str or list of strings
+        :param cidr_ip: The CIDR block
+
+        :rtype: bool
+        :return: ``True`` if an existing rule matches supplied parameters;
+                 ``False`` otherwise.
+        """
+        for rule in rules:
+            if rule.ip_protocol == ip_protocol and rule.from_port == from_port \
+               and rule.to_port == to_port and rule.cidr_ip == cidr_ip:
+                return True
+        return False
+
     @property
     def id(self):
         """

+ 29 - 3
cloudbridge/providers/interfaces/resources.py

@@ -771,13 +771,13 @@ class SecurityGroup(object):
         ip-based rule.
 
         :type ip_protocol: str
-        :param ip_protocol: Either ``tcp`` | ``udp`` | ``icmp``
+        :param ip_protocol: Either ``tcp`` | ``udp`` | ``icmp``.
 
         :type from_port: int
-        :param from_port: The beginning port number you are enabling
+        :param from_port: The beginning port number you are enabling.
 
         :type to_port: int
-        :param to_port: The ending port number you are enabling
+        :param to_port: The ending port number you are enabling.
 
         :type cidr_ip: str or list of strings
         :param cidr_ip: The CIDR block you are providing access to.
@@ -790,6 +790,32 @@ class SecurityGroup(object):
         """
         pass
 
+    @abstractmethod
+    def rule_exists(self, rules, from_port, to_port, ip_protocol, cidr_ip):
+        """
+        Check if an authorization rule with supplied parameters exists.
+
+        :type rules: list of :class:``.SecurityGroupRule`` SecurityGroupRule
+        :param rules: A list of rules to check against
+
+        :type ip_protocol: str
+        :param ip_protocol: Either ``tcp`` | ``udp`` | ``icmp``
+
+        :type from_port: int
+        :param from_port: The beginning port number
+
+        :type to_port: int
+        :param to_port: The ending port number
+
+        :type cidr_ip: str or list of strings
+        :param cidr_ip: The CIDR block
+
+        :rtype: bool
+        :return: ``True`` if an existing rule matches supplied parameters;
+                 ``False`` otherwise.
+        """
+        pass
+
 
 class SecurityGroupRule(object):
 

+ 6 - 0
test/test_provider_security_service.py

@@ -112,6 +112,12 @@ class ProviderSecurityServiceTestCase(ProviderTestBase):
                                               sg.rules[0].to_port)),
                 ("Security group rule repr {0} not matching expected format."
                  .format(sg.rules[0])))
+            self.assertTrue(
+                sg == sg,
+                "The same security groups should be equal?")
+            self.assertFalse(
+                sg != sg,
+                "The same security groups should still be equal?")
             sg.delete()
             sgl = self.provider.security.security_groups.list()
             found_sg = [g for g in sgl if g.name == name]