Browse Source

Group Policy API-3 HEAT resources: Contracts

This is the third patch in the Group Policy resources implementation
series. This patch implements:
    Contracts

In the context of larger Group Policy model, Contracts contain Policy
Rules and Endpoint Groups consume or provide Contracts.

Change-Id: I9d92913f656af5a5d177f0cff5f3b306ced06fdf
Implements: blueprint group-based-policy-automation
Hemanth Ravi 4 years ago
parent
commit
ca098b6bc5

+ 85
- 6
gbpautomation/heat/engine/resources/neutron/grouppolicy.py View File

@@ -30,9 +30,9 @@ class Endpoint(gbpresource.GBPResource):
30 30
     )
31 31
 
32 32
     ATTRIBUTES = (
33
-        NEUTRON_PORT_ID
33
+        PORT_ID
34 34
     ) = (
35
-        'neutron_port_id'
35
+        'port_id'
36 36
     )
37 37
 
38 38
     properties_schema = {
@@ -59,7 +59,7 @@ class Endpoint(gbpresource.GBPResource):
59 59
     }
60 60
 
61 61
     attributes_schema = {
62
-        NEUTRON_PORT_ID: attributes.Schema(
62
+        PORT_ID: attributes.Schema(
63 63
             _("Neutron port id of this endpoint")
64 64
         )
65 65
     }
@@ -84,8 +84,8 @@ class Endpoint(gbpresource.GBPResource):
84 84
     def _resolve_attribute(self, name):
85 85
         client = self.grouppolicy()
86 86
         ep_id = self.resource_id
87
-        if name == 'neutron_port_id':
88
-            return client.show_endpoint(ep_id)['endpoint']['neutron_port_id']
87
+        if name == 'port_id':
88
+            return client.show_endpoint(ep_id)['endpoint']['port_id']
89 89
         return super(Endpoint, self)._resolve_attribute(name)
90 90
 
91 91
     def handle_delete(self):
@@ -585,6 +585,84 @@ class PolicyRule(gbpresource.GBPResource):
585 585
                 self.resource_id, {'policy_rule': prop_diff})
586 586
 
587 587
 
588
+class Contract(gbpresource.GBPResource):
589
+
590
+    PROPERTIES = (
591
+        TENANT_ID, NAME, DESCRIPTION, PARENT_ID, CHILD_CONTRACTS,
592
+        POLICY_RULES
593
+    ) = (
594
+        'tenant_id', 'name', 'description', 'parent_id', 'child_contracts',
595
+        'policy_rules'
596
+    )
597
+
598
+    properties_schema = {
599
+        TENANT_ID: properties.Schema(
600
+            properties.Schema.STRING,
601
+            _('Tenant id of the contract.')
602
+        ),
603
+        NAME: properties.Schema(
604
+            properties.Schema.STRING,
605
+            _('Name of the contract.'),
606
+            update_allowed=True
607
+        ),
608
+        DESCRIPTION: properties.Schema(
609
+            properties.Schema.STRING,
610
+            _('Description of the contract.'),
611
+            update_allowed=True
612
+        ),
613
+        PARENT_ID: properties.Schema(
614
+            properties.Schema.STRING,
615
+            _('Parent id of the contract.'),
616
+            update_allowed=False
617
+        ),
618
+        CHILD_CONTRACTS: properties.Schema(
619
+            properties.Schema.LIST,
620
+            _('List of child contracts.'),
621
+            default=None, update_allowed=True
622
+        ),
623
+        POLICY_RULES: properties.Schema(
624
+            properties.Schema.LIST,
625
+            _('List of policy rules.'),
626
+            default=None, update_allowed=True
627
+        )
628
+    }
629
+
630
+    def _show_resource(self):
631
+        client = self.grouppolicy()
632
+        contract_id = self.resource_id
633
+        return client.show_contract(contract_id)['contract']
634
+
635
+    def handle_create(self):
636
+        client = self.grouppolicy()
637
+
638
+        props = {}
639
+        for key in self.properties:
640
+            if self.properties.get(key) is not None:
641
+                props[key] = self.properties.get(key)
642
+
643
+        contract = client.create_contract(
644
+            {'contract': props})['contract']
645
+
646
+        self.resource_id_set(contract['id'])
647
+
648
+    def handle_delete(self):
649
+
650
+        client = self.grouppolicy()
651
+        contract_id = self.resource_id
652
+
653
+        try:
654
+            client.delete_contract(contract_id)
655
+        except NeutronClientException as ex:
656
+            self.client_plugin().ignore_not_found(ex)
657
+        else:
658
+            return self._delete_task()
659
+
660
+    def handle_update(self, json_snippet, tmpl_diff, prop_diff):
661
+        if prop_diff:
662
+            self.grouppolicy().update_contract(
663
+                self.resource_id, {'contract': prop_diff})
664
+
665
+
588 666
 def resource_mapping():
589 667
     return {
590 668
         'OS::Neutron::Endpoint': Endpoint,
@@ -593,5 +671,6 @@ def resource_mapping():
593 671
         'OS::Neutron::L3Policy': L3Policy,
594 672
         'OS::Neutron::PolicyClassifier': PolicyClassifier,
595 673
         'OS::Neutron::PolicyAction': PolicyAction,
596
-        'OS::Neutron::PolicyRule': PolicyRule
674
+        'OS::Neutron::PolicyRule': PolicyRule,
675
+        'OS::Neutron::Contract': Contract
597 676
     }

+ 139
- 7
gbpautomation/heat/tests/test_grouppolicy.py View File

@@ -119,8 +119,8 @@ policy_classifier_template = '''
119 119
                 "protocol": "tcp",
120 120
                 "port_range": "8000-9000",
121 121
                 "direction": "bi"
122
-        }
123
-     }
122
+      }
123
+    }
124 124
   }
125 125
 }
126 126
 '''
@@ -138,8 +138,8 @@ policy_action_template = '''
138 138
                 "description": "test policy action resource",
139 139
                 "action_type": "redirect",
140 140
                 "action_value": "7890"
141
-        }
142
-     }
141
+      }
142
+    }
143 143
   }
144 144
 }
145 145
 '''
@@ -147,7 +147,7 @@ policy_action_template = '''
147 147
 policy_rule_template = '''
148 148
 {
149 149
  "AWSTemplateFormatVersion" : "2010-09-09",
150
-  "Description" : "Template to test neutron l3 policy",
150
+  "Description" : "Template to test neutron policy rule",
151 151
   "Parameters" : {},
152 152
   "Resources" : {
153 153
   "policy_rule": {
@@ -164,6 +164,26 @@ policy_rule_template = '''
164 164
 }
165 165
 '''
166 166
 
167
+contract_template = '''
168
+{
169
+ "AWSTemplateFormatVersion" : "2010-09-09",
170
+  "Description" : "Template to test contract",
171
+  "Parameters" : {},
172
+  "Resources" : {
173
+  "contract": {
174
+      "Type": "OS::Neutron::Contract",
175
+      "Properties": {
176
+          "name": "test-contract",
177
+          "description": "test contract resource",
178
+          "parent_id": "3456",
179
+          "child_contracts": ["7890", "1234"],
180
+          "policy_rules": ["2345", "6789"]
181
+      }
182
+    }
183
+  }
184
+}
185
+'''
186
+
167 187
 
168 188
 class EndpointTest(HeatTestCase):
169 189
 
@@ -263,10 +283,10 @@ class EndpointTest(HeatTestCase):
263 283
         rsrc = self.create_endpoint()
264 284
         gbpclient.Client.show_endpoint('5678').MultipleTimes(
265 285
         ).AndReturn(
266
-            {'endpoint': {'neutron_port_id': '1234'}})
286
+            {'endpoint': {'port_id': '1234'}})
267 287
         self.m.ReplayAll()
268 288
         scheduler.TaskRunner(rsrc.create)()
269
-        self.assertEqual('1234', rsrc.FnGetAtt('neutron_port_id'))
289
+        self.assertEqual('1234', rsrc.FnGetAtt('port_id'))
270 290
         self.m.VerifyAll()
271 291
 
272 292
     def test_attribute_failed(self):
@@ -974,3 +994,115 @@ class PolicyRuleTest(HeatTestCase):
974 994
         scheduler.TaskRunner(rsrc.update, update_template)()
975 995
 
976 996
         self.m.VerifyAll()
997
+
998
+
999
+class ContractTest(HeatTestCase):
1000
+
1001
+    def setUp(self):
1002
+        super(ContractTest, self).setUp()
1003
+        self.m.StubOutWithMock(gbpclient.Client, 'create_contract')
1004
+        self.m.StubOutWithMock(gbpclient.Client, 'delete_contract')
1005
+        self.m.StubOutWithMock(gbpclient.Client, 'show_contract')
1006
+        self.m.StubOutWithMock(gbpclient.Client, 'update_contract')
1007
+        self.stub_keystoneclient()
1008
+
1009
+    def create_contract(self):
1010
+        gbpclient.Client.create_contract({
1011
+            'contract': {
1012
+                "name": "test-contract",
1013
+                "description": "test contract resource",
1014
+                "parent_id": "3456",
1015
+                "child_contracts": ["7890", "1234"],
1016
+                "policy_rules": ["2345", "6789"]
1017
+            }
1018
+        }).AndReturn({'contract': {'id': '5678'}})
1019
+
1020
+        snippet = template_format.parse(contract_template)
1021
+        stack = utils.parse_stack(snippet)
1022
+        resource_defns = stack.t.resource_definitions(stack)
1023
+        return grouppolicy.Contract(
1024
+            'contract', resource_defns['contract'], stack)
1025
+
1026
+    def test_create(self):
1027
+        rsrc = self.create_contract()
1028
+        self.m.ReplayAll()
1029
+        scheduler.TaskRunner(rsrc.create)()
1030
+        self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
1031
+        self.m.VerifyAll()
1032
+
1033
+    def test_create_failed(self):
1034
+        gbpclient.Client.create_contract({
1035
+            'contract': {
1036
+                "name": "test-contract",
1037
+                "description": "test contract resource",
1038
+                "parent_id": "3456",
1039
+                "child_contracts": ["7890", "1234"],
1040
+                "policy_rules": ["2345", "6789"]
1041
+            }
1042
+        }).AndRaise(grouppolicy.NeutronClientException())
1043
+        self.m.ReplayAll()
1044
+
1045
+        snippet = template_format.parse(contract_template)
1046
+        stack = utils.parse_stack(snippet)
1047
+        resource_defns = stack.t.resource_definitions(stack)
1048
+        rsrc = grouppolicy.Contract(
1049
+            'contract', resource_defns['contract'], stack)
1050
+
1051
+        error = self.assertRaises(exception.ResourceFailure,
1052
+                                  scheduler.TaskRunner(rsrc.create))
1053
+        self.assertEqual(
1054
+            'NeutronClientException: An unknown exception occurred.',
1055
+            str(error))
1056
+        self.assertEqual((rsrc.CREATE, rsrc.FAILED), rsrc.state)
1057
+        self.m.VerifyAll()
1058
+
1059
+    def test_delete(self):
1060
+        gbpclient.Client.delete_contract('5678')
1061
+        gbpclient.Client.show_contract('5678').AndRaise(
1062
+            grouppolicy.NeutronClientException(status_code=404))
1063
+
1064
+        rsrc = self.create_contract()
1065
+        self.m.ReplayAll()
1066
+        scheduler.TaskRunner(rsrc.create)()
1067
+        scheduler.TaskRunner(rsrc.delete)()
1068
+        self.assertEqual((rsrc.DELETE, rsrc.COMPLETE), rsrc.state)
1069
+        self.m.VerifyAll()
1070
+
1071
+    def test_delete_already_gone(self):
1072
+        gbpclient.Client.delete_contract('5678').AndRaise(
1073
+            grouppolicy.NeutronClientException(status_code=404))
1074
+
1075
+        rsrc = self.create_contract()
1076
+        self.m.ReplayAll()
1077
+        scheduler.TaskRunner(rsrc.create)()
1078
+        scheduler.TaskRunner(rsrc.delete)()
1079
+        self.assertEqual((rsrc.DELETE, rsrc.COMPLETE), rsrc.state)
1080
+        self.m.VerifyAll()
1081
+
1082
+    def test_delete_failed(self):
1083
+        gbpclient.Client.delete_contract('5678').AndRaise(
1084
+            grouppolicy.NeutronClientException(status_code=400))
1085
+
1086
+        rsrc = self.create_contract()
1087
+        self.m.ReplayAll()
1088
+        scheduler.TaskRunner(rsrc.create)()
1089
+        error = self.assertRaises(exception.ResourceFailure,
1090
+                                  scheduler.TaskRunner(rsrc.delete))
1091
+        self.assertEqual(
1092
+            'NeutronClientException: An unknown exception occurred.',
1093
+            str(error))
1094
+        self.assertEqual((rsrc.DELETE, rsrc.FAILED), rsrc.state)
1095
+        self.m.VerifyAll()
1096
+
1097
+    def test_update(self):
1098
+        rsrc = self.create_contract()
1099
+        gbpclient.Client.update_contract(
1100
+            '5678', {'contract': {'child_contracts': ["1234"]}})
1101
+        self.m.ReplayAll()
1102
+        scheduler.TaskRunner(rsrc.create)()
1103
+
1104
+        update_template = copy.deepcopy(rsrc.t)
1105
+        update_template['Properties']['child_contracts'] = ["1234"]
1106
+        scheduler.TaskRunner(rsrc.update, update_template)()
1107
+
1108
+        self.m.VerifyAll()

Loading…
Cancel
Save