diff --git a/ec2_rule_service.py b/ec2_rule_service.py new file mode 100644 index 0000000..ab07ff7 --- /dev/null +++ b/ec2_rule_service.py @@ -0,0 +1,9 @@ +class EC2RuleService: + + def __init__(self, ec2_connection, ec2_rule_transformer): + self.ec2_connection = ec2_connection + self.ec2_rule_transformer = ec2_rule_transformer + + def get_rules_for_group(self, group_name): + group = self.ec2_connection.get_all_security_groups(groupnames=group_name)[0] + return set([self.ec2_rule_transformer.to_rule(rule) for rule in group.rules]) \ No newline at end of file diff --git a/openstack_group_service.py b/openstack_group_service.py new file mode 100644 index 0000000..0b578f8 --- /dev/null +++ b/openstack_group_service.py @@ -0,0 +1,7 @@ +class OpenstackGroupService(): + + def __init__(self, security_group_manager): + self.security_group_manager = security_group_manager + + def get_group(self, group_name): + return [group for group in self.security_group_manager.list() if group.name == group_name][0] \ No newline at end of file diff --git a/openstack_rule_service.py b/openstack_rule_service.py new file mode 100644 index 0000000..37765fe --- /dev/null +++ b/openstack_rule_service.py @@ -0,0 +1,9 @@ +class OpenstackRuleService: + def __init__(self, group_service, openstack_rule_transformer): + self.group_service = group_service + self.openstack_rule_transformer = openstack_rule_transformer + + def get_rules_for_group(self, group_name): + openstack_group = self.group_service.get_group(group_name) + return set([self.openstack_rule_transformer.to_rule(rule) for rule in openstack_group.rules]) + # return self.group_service.get_group(group_name).rules \ No newline at end of file diff --git a/rule_refresher.py b/rule_refresher.py index 73d7fd9..0e64921 100644 --- a/rule_refresher.py +++ b/rule_refresher.py @@ -1,27 +1,27 @@ class RuleRefresher: - def __init__(self, openstack_group_manager, ec2_conn, openstack_group_transformer, ec2_group_transformer): - self.openstack_group_manager = openstack_group_manager + def __init__(self, ec2_conn, openstack_rule_service, ec2_rule_service): self.ec2_conn = ec2_conn - self.openstack_group_transformer = openstack_group_transformer - self.ec2_group_transformer = ec2_group_transformer + self.openstack_rule_service = openstack_rule_service + self.ec2_rule_service = ec2_rule_service def refresh(self, openstack_instance): for group_dict in openstack_instance.security_groups: - openstack_group = [group for group in self.openstack_group_manager.list() if group.name == group_dict['name']][0] - transformed_openstack_group = self.openstack_group_transformer.to_group(openstack_group) + # openstack_group = [group for group in self.openstack_group_manager.list() if group.name == group_dict['name']][0] + # transformed_openstack_group = self.openstack_group_transformer.to_group(openstack_group) + # ec2_group = self.ec2_conn.get_all_security_groups(groupnames=group_dict['name'])[0] + # transformed_ec2_group = self.ec2_group_transformer.to_group(ec2_group) - ec2_group = self.ec2_conn.get_all_security_groups(groupnames=group_dict['name'])[0] - transformed_ec2_group = self.ec2_group_transformer.to_group(ec2_group) + # TODO: transform openstack rules before finding difference + openstack_rules = self.openstack_rule_service.get_rules_for_group(group_dict['name']) + ec2_rules = self.ec2_rule_service.get_rules_for_group(group_dict['name']) - rules_in_openstack_group_not_in_ec2 = transformed_openstack_group.rule_diff(transformed_ec2_group) + for rule in openstack_rules - ec2_rules: + self._create_rule_on_ec2(group_dict['name'], rule) - for rule in rules_in_openstack_group_not_in_ec2: - self._create_rule_on_ec2(openstack_group, rule) - - def _create_rule_on_ec2(self, openstack_group, rule): + def _create_rule_on_ec2(self, group_name, rule): self.ec2_conn.authorize_security_group( - group_name=openstack_group.name, + group_name=group_name, ip_protocol=rule.ip_protocol, from_port=rule.from_port, to_port=rule.to_port, diff --git a/tests/test_ec2_rule_service.py b/tests/test_ec2_rule_service.py new file mode 100644 index 0000000..d50adcd --- /dev/null +++ b/tests/test_ec2_rule_service.py @@ -0,0 +1,50 @@ +import unittest + +from boto.ec2 import EC2Connection +from boto.ec2.securitygroup import SecurityGroup +from mock import Mock, call + +from nova.virt.ec2.ec2_rule_service import EC2RuleService +from nova.virt.ec2.ec2_rule_transformer import EC2RuleTransformer +from nova.virt.ec2.tests.fake_ec2_rule_builder import FakeEC2RuleBuilder + +class TestEC2RuleService(unittest.TestCase): + + def setUp(self): + self.security_group = Mock(spec=SecurityGroup) + self.security_group.name = "secGroup" + + self.ec2_connection = Mock(spec=EC2Connection) + self.ec2_connection.get_all_security_groups.return_value = [self.security_group] + self.ec2_rule_transformer = Mock(spec=EC2RuleTransformer) + + self.ec2_rule_service = EC2RuleService(self.ec2_connection, self.ec2_rule_transformer) + + def test_should_get_security_group_from_ec2_connection(self): + self.security_group.rules = [] + + self.ec2_rule_service.get_rules_for_group(self.security_group.name) + + self.ec2_connection.get_all_security_groups.assert_called_once_with(groupnames=self.security_group.name) + + def test_should_transform_rules_from_security_group(self): + first_rule = Mock() + second_rule = Mock() + self.security_group.rules = [first_rule, second_rule] + + self.ec2_rule_service.get_rules_for_group(self.security_group.name) + + self.ec2_rule_transformer.to_rule.assert_has_calls([call(first_rule), call(second_rule)]) + + def test_should_return_transformed_security_group_rules(self): + first_rule = Mock() + second_rule = Mock() + self.security_group.rules = [first_rule, second_rule] + + first_transformed_rule = Mock() + second_transformed_rule = Mock() + self.ec2_rule_transformer.to_rule.side_effect = [first_transformed_rule, second_transformed_rule] + + actual_rules = self.ec2_rule_service.get_rules_for_group(self.security_group.name) + + self.assertEqual(actual_rules, set([first_transformed_rule, second_transformed_rule])) \ No newline at end of file diff --git a/tests/test_openstack_group_service.py b/tests/test_openstack_group_service.py new file mode 100644 index 0000000..362e209 --- /dev/null +++ b/tests/test_openstack_group_service.py @@ -0,0 +1,27 @@ +import unittest +from mock import Mock +from novaclient.v1_1.security_groups import SecurityGroupManager +from nova.virt.ec2.openstack_group_service import OpenstackGroupService + + +class TestOpenstackGroupService(unittest.TestCase): + + def setUp(self): + self.security_group_manager = Mock(spec=SecurityGroupManager) + self.openstack_group_service = OpenstackGroupService(self.security_group_manager) + + def test_should_get_group_from_nova_security_group_manager(self): + security_group = Mock() + security_group.name = 'secGroup' + self.security_group_manager.list.return_value = [security_group] + + self.assertEqual(self.openstack_group_service.get_group(security_group.name), security_group) + + def test_should_get_group_from_nova_security_group_manager_when_multiple_groups_present(self): + security_group1 = Mock() + security_group1.name = 'secGroup' + security_group2 = Mock() + security_group2.name = 'otherGroup' + self.security_group_manager.list.return_value = [security_group1, security_group2] + + self.assertEqual(self.openstack_group_service.get_group(security_group2.name), security_group2) \ No newline at end of file diff --git a/tests/test_openstack_rule_service.py b/tests/test_openstack_rule_service.py new file mode 100644 index 0000000..3297338 --- /dev/null +++ b/tests/test_openstack_rule_service.py @@ -0,0 +1,52 @@ +import unittest + +from mock import Mock, call +from novaclient.v1_1.security_groups import SecurityGroup + +from nova.virt.ec2.openstack_rule_service import OpenstackRuleService +from nova.virt.ec2.openstack_group_service import OpenstackGroupService +from nova.virt.ec2.openstack_rule_transformer import OpenstackRuleTransformer + + +class TestOpenstackRuleService(unittest.TestCase): + def setUp(self): + self.security_group = Mock(spec=SecurityGroup) + self.security_group.name = "secGroup" + + self.openstack_group_service = Mock(OpenstackGroupService) + self.openstack_group_service.get_group.return_value = self.security_group + self.openstack_rule_transformer = Mock(OpenstackRuleTransformer) + + self.openstack_rule_service = OpenstackRuleService( + self.openstack_group_service, + self.openstack_rule_transformer + ) + + def test_should_get_security_group_from_group_service(self): + self.security_group.rules = [] + + self.openstack_rule_service.get_rules_for_group(self.security_group.name) + + self.openstack_group_service.get_group.assert_called_once_with(self.security_group.name) + + def test_should_transform_rules_from_security_group(self): + first_rule = Mock() + second_rule = Mock() + self.security_group.rules = [first_rule, second_rule] + + self.openstack_rule_service.get_rules_for_group(self.security_group.name) + + self.openstack_rule_transformer.to_rule.assert_has_calls([call(first_rule), call(second_rule)]) + + def test_should_return_transformed_security_group_rules(self): + first_rule = Mock() + second_rule = Mock() + self.security_group.rules = [first_rule, second_rule] + + first_transformed_rule = Mock() + second_transformed_rule = Mock() + self.openstack_rule_transformer.to_rule.side_effect = [first_transformed_rule, second_transformed_rule] + + actual_rules = self.openstack_rule_service.get_rules_for_group(self.security_group.name) + + self.assertEqual(actual_rules, set([first_transformed_rule, second_transformed_rule])) diff --git a/tests/test_rule_refresher.py b/tests/test_rule_refresher.py index e4bddee..04db6c1 100644 --- a/tests/test_rule_refresher.py +++ b/tests/test_rule_refresher.py @@ -2,92 +2,61 @@ import unittest from boto.ec2 import EC2Connection from mock import Mock -import novaclient -from novaclient.v1_1.servers import Server from nova.virt.ec2.rule_refresher import RuleRefresher + from nova.virt.ec2.rule import Rule -from nova.virt.ec2.ec2_group_transformer import EC2GroupTransformer -from nova.virt.ec2.openstack_group_transformer import OpenstackGroupTransformer -from nova.virt.ec2.group import Group +from nova.virt.ec2.openstack_rule_service import OpenstackRuleService +from nova.virt.ec2.ec2_rule_service import EC2RuleService GROUP_NAME = 'secGroup' OTHER_GROUP_NAME = "otherSecGroup" class TestRuleRefresher(unittest.TestCase): def setUp(self): - self.new_openstack_rule = {'ip_protocol': 'abc', 'from_port': 1111, 'to_port': 2222, 'ip_range': {'cidr': '1.2.3.4/55'}} - + self.new_rule = Rule('hjkl', 7, 8, '9.9.9.9/99') self.openstack_instance = Mock() - self.openstack_instance.security_groups = [{'name': GROUP_NAME}] - self.openstack_group = Mock() - self.openstack_group.name = GROUP_NAME - self.openstack_group_manager = Mock(spec=novaclient.v1_1.security_groups.SecurityGroupManager) - self.openstack_group_manager.list.return_value = [self.openstack_group] + self.ec2_connection = Mock(EC2Connection) + self.openstack_rule_service = Mock(OpenstackRuleService) + self.ec2_rule_service = Mock(EC2RuleService) - self.ec2_group = Mock() - self.ec2_group.name = GROUP_NAME - self.ec2_connection = Mock(spec=EC2Connection) - self.ec2_connection.get_all_security_groups.return_value = [self.ec2_group] - - self.openstack_group_transformer = Mock(spec=OpenstackGroupTransformer) - self.ec2_group_transformer = Mock(spec=EC2GroupTransformer) - - self.rule_refresher = RuleRefresher(self.openstack_group_manager, self.ec2_connection, - self.openstack_group_transformer, self.ec2_group_transformer) + self.rule_refresher = RuleRefresher( + self.ec2_connection, + self.openstack_rule_service, + self.ec2_rule_service + ) def test_should_add_rule_to_ec2_security_group_when_rule_associated_with_group_on_openstack(self): - new_rule = Rule('hjkl', 7, 8, '9.9.9.9/99') - transformed_openstack_group = Mock(spec=Group) - transformed_openstack_group.rule_diff.return_value = [new_rule] - self.openstack_group_transformer.to_group.return_value = transformed_openstack_group + self.openstack_instance.security_groups = [{'name': GROUP_NAME}] + + self.openstack_rule_service.get_rules_for_group.return_value = set([self.new_rule]) + self.ec2_rule_service.get_rules_for_group.return_value = set() self.rule_refresher.refresh(self.openstack_instance) self.ec2_connection.authorize_security_group.assert_called_once_with( group_name=GROUP_NAME, - ip_protocol=new_rule.ip_protocol, - from_port=new_rule.from_port, - to_port=new_rule.to_port, - cidr_ip=new_rule.ip_range + ip_protocol=self.new_rule.ip_protocol, + from_port=self.new_rule.from_port, + to_port=self.new_rule.to_port, + cidr_ip=self.new_rule.ip_range ) def test_should_add_rule_to_corresponding_ec2_group_when_other_groups_present(self): - openstack_group_with_new_rule = Mock() - openstack_group_with_new_rule.name = OTHER_GROUP_NAME - other_ec2_group = Mock() - self.openstack_instance.security_groups = [{'name': GROUP_NAME}, {'name': OTHER_GROUP_NAME}] - self.openstack_group_manager.list.return_value = [openstack_group_with_new_rule, self.openstack_group] - - def mock_get_all_security_groups(groupnames=None): - if groupnames == other_ec2_group.name: - return [other_ec2_group] - return [self.ec2_group] - self.ec2_connection.get_all_security_groups.side_effect = mock_get_all_security_groups - - new_rule = Rule('hjkl', 7, 8, '9.9.9.9/99') - transformed_openstack_group = Mock(spec=Group) - transformed_openstack_group.rule_diff.return_value = [] - transformed_openstack_group_with_new_rule = Mock(spec=Group) - transformed_openstack_group_with_new_rule.rule_diff.return_value = [new_rule] - - def mock_openstack_to_group(openstack_group): - if openstack_group == self.openstack_group: - return transformed_openstack_group - else: - return transformed_openstack_group_with_new_rule - self.openstack_group_transformer.to_group.side_effect = mock_openstack_to_group - + def mock_get_rules_for_openstack_group(group_name): + return set() if group_name == GROUP_NAME else set([self.new_rule]) + self.openstack_rule_service.get_rules_for_group.side_effect = mock_get_rules_for_openstack_group + self.ec2_rule_service.get_rules_for_group.return_value = set() self.rule_refresher.refresh(self.openstack_instance) self.ec2_connection.authorize_security_group.assert_called_once_with( group_name=OTHER_GROUP_NAME, - ip_protocol=new_rule.ip_protocol, - from_port=new_rule.from_port, - to_port=new_rule.to_port, - cidr_ip=new_rule.ip_range + ip_protocol=self.new_rule.ip_protocol, + from_port=self.new_rule.from_port, + to_port=self.new_rule.to_port, + cidr_ip=self.new_rule.ip_range ) \ No newline at end of file