diff --git a/doc/source/data/lbaas.csv b/doc/source/data/lbaas.csv index ed4925d..ad0d46b 100644 --- a/doc/source/data/lbaas.csv +++ b/doc/source/data/lbaas.csv @@ -8,11 +8,11 @@ lbaas-l7policy-delete,loadbalancer l7policy delete,LBaaS v2 Delete a given L7 po lbaas-l7policy-list,loadbalancer l7policy list,LBaaS v2 List L7 policies that belong to a given listener. lbaas-l7policy-show,loadbalancer l7policy show,LBaaS v2 Show information of a given L7 policy. lbaas-l7policy-update,loadbalancer l7policy set,LBaaS v2 Update a given L7 policy. -lbaas-l7rule-create,,LBaaS v2 Create L7 rule. -lbaas-l7rule-delete,,LBaaS v2 Delete a given L7 rule. -lbaas-l7rule-list,,LBaaS v2 List L7 rules that belong to a given L7 policy. -lbaas-l7rule-show,,LBaaS v2 Show information of a given rule. -lbaas-l7rule-update,,LBaaS v2 Update a given L7 rule. +lbaas-l7rule-create,loadbalancer l7rule create,LBaaS v2 Create L7 rule. +lbaas-l7rule-delete,loadbalancer l7rule delete,LBaaS v2 Delete a given L7 rule. +lbaas-l7rule-list,loadbalancer l7rule list,LBaaS v2 List L7 rules that belong to a given L7 policy. +lbaas-l7rule-show,loadbalancer l7rule show,LBaaS v2 Show information of a given rule. +lbaas-l7rule-update,loadbalancer l7rule set,LBaaS v2 Update a given L7 rule. lbaas-listener-create,loadbalancer listener create,LBaaS v2 Create a listener. lbaas-listener-delete,loadbalancer listener delete,LBaaS v2 Delete a given listener. lbaas-listener-list,loadbalancer listener list,LBaaS v2 List listeners that belong to a given tenant. diff --git a/doc/source/usage/osc/v2/load-balancer.rst b/doc/source/usage/osc/v2/load-balancer.rst index 8f487a1..d71aa89 100644 --- a/doc/source/usage/osc/v2/load-balancer.rst +++ b/doc/source/usage/osc/v2/load-balancer.rst @@ -850,3 +850,177 @@ Delete a l7policy .. describe:: L7policy to delete (name or ID). + +====== +l7rule +====== + +loadbalancer l7rule list +------------------------ + +List l7rules for l7policy + +.. program:: loadbalancer l7rule list +.. code:: bash + + openstack loadbalancer l7rule list + --l7policy + +.. _loadbalancer_l7rule_list-l7policy: +.. describe:: + + l7policy to list rules for (name or ID). + +loadbalancer l7rule show +------------------------ + +Show the details of a single l7rule + +.. program:: loadbalancer l7rule show +.. code:: bash + + openstack loadbalancer l7rule show + + + +.. _loadbalancer_l7rule_show-l7policy: +.. describe:: + + l7policy to show rule from (name or ID) + +.. _loadbalancer_l7rule_show-rule-id: +.. describe:: + + l7rule to show + +loadbalancer l7rule create +-------------------------- + +Create a l7rule + +.. program:: loadbalancer l7rule create +.. code:: bash + + openstack loadbalancer l7rule create + --compare-type {'REGEX','EQUAL_TO','CONTAINS','ENDS_WITH','STARTS_WITH'} + [--invert] + --value + [--key ] + [--project ] + --type {'FILE_TYPE','PATH','COOKIE','HOST_NAME','HEADER'} + [--enable | --disable] + + +.. option:: --compare-type {'REGEX','EQUAL_TO','CONTAINS','ENDS_WITH','STARTS_WITH'} + + Set the compare type for the l7rule. + +.. option:: --invert + + Invert l7rule. + +.. option:: --value + + Set the rule value to match on. + +.. option:: --key + + Set the key for the l7rule's value to match on. + +.. option:: --project + + Project for the l7rule (name or ID). + +.. option:: --type {'FILE_TYPE','PATH','COOKIE','HOST_NAME','HEADER'} + + Set the type for the l7rule. + +.. option:: --enable + + Enable l7rule (default) + +.. option:: --disable + + Disable l7rule + +.. _loadbalancer_l7rule_create-l7policy: +.. describe:: + + l7policy to add l7rule to (name or ID). + + +loadbalancer l7rule set +----------------------- + +Update a l7rule + +.. program:: loadbalancer l7rule set +.. code:: bash + + openstack loadbalancer l7rule set + [--compare-type {'REGEX','EQUAL_TO','CONTAINS','ENDS_WITH','STARTS_WITH'}] + [--invert] + [--value ] + [--key ] + [--type {'FILE_TYPE','PATH','COOKIE','HOST_NAME','HEADER'}] + [--enable | --disable] + --l7policy + + +.. option:: --compare-type {'REGEX','EQUAL_TO','CONTAINS','ENDS_WITH','STARTS_WITH'} + + Set the compare type for the l7rule. + +.. option:: --invert + + Invert l7rule. + +.. option:: --value + + Set the rule value to match on. + +.. option:: --key + + Set the key for the l7rule's value to match on. + +.. option:: --type {'FILE_TYPE','PATH','COOKIE','HOST_NAME','HEADER'} + + Set the type for the l7rule. + +.. option:: --enable + + Enable l7rule. + +.. option:: --disable + + Disable l7rule. + +.. _loadbalancer_l7rule_set-l7policy: +.. describe:: + + L7policy to update l7rule on (name or ID) + +.. _loadbalancer_l7rule_set-l7rule_id: +.. describe:: + + l7rule to update + +loadbalancer l7rule delete +-------------------------- + +.. program:: loadbalancer l7rule delete +.. code:: bash + + openstack loadbalancer l7rule delete + + + +.. _loadbalancer_l7rule_delete-l7policy: +.. describe:: + + l7policy to delete rule from (name or ID). + +.. _loadbalancer_l7rule_delete-l7rule_id: +.. describe:: + + l7rule to delete. diff --git a/octaviaclient/api/constants.py b/octaviaclient/api/constants.py index 2f75efc..43989da 100644 --- a/octaviaclient/api/constants.py +++ b/octaviaclient/api/constants.py @@ -29,4 +29,4 @@ BASE_SINGLE_MONITOR_URL = '/healthmonitors/{uuid}' BASE_L7POLICY_URL = '/l7policies' BASE_SINGLE_L7POLICY_URL = BASE_L7POLICY_URL + '/{policy_uuid}' BASE_L7RULE_URL = BASE_SINGLE_L7POLICY_URL + '/rules' -BASE_SINGLE_L7RULE_URL = BASE_SINGLE_L7POLICY_URL + '/{rule_uuid}' +BASE_SINGLE_L7RULE_URL = BASE_SINGLE_L7POLICY_URL + '/rules/{rule_uuid}' diff --git a/octaviaclient/api/load_balancer_v2.py b/octaviaclient/api/load_balancer_v2.py index fc3c585..4c62d27 100644 --- a/octaviaclient/api/load_balancer_v2.py +++ b/octaviaclient/api/load_balancer_v2.py @@ -196,7 +196,7 @@ class APIv2(api.BaseAPI): """Delete a pool :param string pool_id: - ID of of listener to delete + ID of of pool to delete :return: Response Code from the API """ @@ -344,7 +344,7 @@ class APIv2(api.BaseAPI): """Delete a l7policy :param string l7policy_id: - ID of of listener to delete + ID of of l7policy to delete :return: Response Code from the API """ @@ -380,3 +380,81 @@ class APIv2(api.BaseAPI): response = self.create(url, method='PUT', **kwargs) return response + + def l7rule_list(self, l7policy_id, **kwargs): + """List all l7rules for a l7policy + + :param kwargs: + Parameters to filter on (not implemented) + :return: + List of l7policies + """ + url = const.BASE_L7RULE_URL.format(policy_uuid=l7policy_id) + rule_list = self.list(url, **kwargs) + + return rule_list + + def l7rule_create(self, l7policy_id, **kwargs): + """Create a l7rule + + :param string l7policy_id: + The l7policy to create the l7rule for + :param kwargs: + Parameters to create a l7rule with (expects json=) + :return: + A dict of the created l7rule's settings + """ + url = const.BASE_L7RULE_URL.format(policy_uuid=l7policy_id) + rule = self.create(url, **kwargs) + + return rule + + def l7rule_delete(self, l7rule_id, l7policy_id): + """Delete a l7rule + + :param string l7rule_id: + ID of of listener to delete + :param string l7policy_id: + ID of the l7policy for this l7rule + :return: + Response Code from the API + """ + url = const.BASE_SINGLE_L7RULE_URL.format(rule_uuid=l7rule_id, + policy_uuid=l7policy_id) + response = self.delete(url) + + return response + + def l7rule_show(self, l7rule_id, l7policy_id): + """Show a l7rule's settings + + :param string l7rule_id: + ID of the l7rule to show + :param string l7policy_id: + ID of the l7policy for this l7rule + :return: + Dict of the specified l7rule's settings + """ + url = const.BASE_L7RULE_URL.format(policy_uuid=l7policy_id) + + rule = self.find(path=url, value=l7rule_id) + + return rule + + def l7rule_set(self, l7rule_id, l7policy_id, **kwargs): + """Update a l7rule's settings + + :param l7rule_id: + ID of the l7rule to update + :param string l7policy_id: + ID of the l7policy for this l7rule + :param kwargs: + A dict of arguments to update a l7rule + :return: + Response Code from the API + """ + url = const.BASE_SINGLE_L7RULE_URL.format(rule_uuid=l7rule_id, + policy_uuid=l7policy_id) + response = self.create(url, method='PUT', **kwargs) + + return response diff --git a/octaviaclient/osc/v2/constants.py b/octaviaclient/osc/v2/constants.py index dc7d2d6..d0d0d4a 100644 --- a/octaviaclient/osc/v2/constants.py +++ b/octaviaclient/osc/v2/constants.py @@ -145,3 +145,28 @@ L7POLICY_COLUMNS = ( 'action', 'position', 'admin_state_up') + +L7RULE_ROWS = ( + 'created_at', + 'compare_type', + 'provisioning_status', + 'invert', + 'admin_state_up', + 'updated_at', + 'value', + 'key', + 'project_id', + 'type', + 'id', + 'operating_status') + +L7RULE_COLUMNS = ( + 'id', + 'project_id', + 'provisioning_status', + 'compare_type', + 'type', + 'key', + 'value', + 'invert', + 'admin_state_up') diff --git a/octaviaclient/osc/v2/l7rule.py b/octaviaclient/osc/v2/l7rule.py new file mode 100644 index 0000000..ff1db12 --- /dev/null +++ b/octaviaclient/osc/v2/l7rule.py @@ -0,0 +1,261 @@ +# 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. +# + +"""L7rule action implementation""" + +from cliff import lister +from osc_lib.command import command +from osc_lib import utils + +from octaviaclient.osc.v2 import constants as const +from octaviaclient.osc.v2 import utils as v2_utils + +COMPARE_TYPES = ['REGEX', 'EQUAL_TO', 'CONTAINS', 'ENDS_WITH', 'STARTS_WITH'] +TYPES = ['FILE_TYPE', 'PATH', 'COOKIE', 'HOST_NAME', 'HEADER'] + + +class CreateL7Rule(command.ShowOne): + """Create a l7rule""" + + def get_parser(self, prog_name): + parser = super(CreateL7Rule, self).get_parser(prog_name) + parser.add_argument( + 'l7policy', + metavar='', + help="l7policy to add l7rule to (name or ID)" + ) + parser.add_argument( + '--compare-type', + metavar='', + required=True, + choices=COMPARE_TYPES, + help="Compare type for the l7rule" + ) + parser.add_argument( + '--invert', + action='store_true', + default=None, + help="Invert l7rule" + ) + parser.add_argument( + '--value', + metavar='', + required=True, + help="Rule value" + ) + parser.add_argument( + '--key', + metavar='', + help="Key for the l7rule" + ) + parser.add_argument( + '--type', + metavar='', + required=True, + choices=TYPES, + help="Type for the l7rule" + ) + admin_group = parser.add_mutually_exclusive_group() + admin_group.add_argument( + '--enable', + action='store_true', + default=True, + help="Enable l7policy (default)" + ) + admin_group.add_argument( + '--disable', + action='store_true', + default=None, + help="Disable l7policy" + ) + + return parser + + def take_action(self, parsed_args): + rows = const.L7RULE_ROWS + attrs = v2_utils.get_l7rule_attrs(self.app.client_manager, + parsed_args) + v2_utils.check_l7rule_attrs(attrs) + + l7policy_id = attrs.pop('l7policy_id') + body = {"rule": attrs} + data = self.app.client_manager.load_balancer.l7rule_create( + l7policy_id=l7policy_id, + json=body + ) + + return (rows, (utils.get_dict_properties( + data['rule'], rows, formatters={}))) + + +class DeleteL7Rule(command.Command): + """Delete a l7rule""" + + def get_parser(self, prog_name): + parser = super(DeleteL7Rule, self).get_parser(prog_name) + + parser.add_argument( + 'l7policy', + metavar="", + help="l7policy to delete rule from (name or ID)" + ) + parser.add_argument( + 'l7rule', + metavar="", + help="l7rule to delete" + ) + + return parser + + def take_action(self, parsed_args): + attrs = v2_utils.get_l7rule_attrs(self.app.client_manager, parsed_args) + + self.app.client_manager.load_balancer.l7rule_delete( + l7rule_id=attrs['l7rule_id'], + l7policy_id=attrs['l7policy_id'] + ) + + +class ListL7Rule(lister.Lister): + """List l7rules for l7policy""" + + def get_parser(self, prog_name): + parser = super(ListL7Rule, self).get_parser(prog_name) + + parser.add_argument( + 'l7policy', + metavar='', + help='l7policy to list rules for (name or ID)' + ) + + return parser + + def take_action(self, parsed_args): + columns = const.L7RULE_COLUMNS + attrs = v2_utils.get_l7rule_attrs(self.app.client_manager, parsed_args) + + data = self.app.client_manager.load_balancer.l7rule_list( + l7policy_id=attrs['l7policy_id'] + ) + + return (columns, + (utils.get_dict_properties( + s, columns, formatters={}) for s in data['rules'])) + + +class ShowL7Rule(command.ShowOne): + """Show the details of a single l7rule""" + + def get_parser(self, prog_name): + parser = super(ShowL7Rule, self).get_parser(prog_name) + + parser.add_argument( + 'l7policy', + metavar="", + help="l7policy to show rule from (name or ID)" + ) + parser.add_argument( + 'l7rule', + metavar="", + help="l7rule to show" + ) + + return parser + + def take_action(self, parsed_args): + rows = const.L7RULE_ROWS + + attrs = v2_utils.get_l7rule_attrs(self.app.client_manager, parsed_args) + data = self.app.client_manager.load_balancer.l7rule_show( + l7rule_id=attrs['l7rule_id'], + l7policy_id=attrs['l7policy_id'] + ) + + return (rows, (utils.get_dict_properties( + data, rows, formatters={}))) + + +class SetL7Rule(command.Command): + """Update a l7rule""" + + def get_parser(self, prog_name): + parser = super(SetL7Rule, self).get_parser(prog_name) + + parser.add_argument( + 'l7policy', + metavar='', + help="L7policy to update rule on (name or ID)" + ) + parser.add_argument( + 'l7rule', + metavar='', + help="l7rule to update" + ) + parser.add_argument( + '--compare-type', + metavar='', + choices=COMPARE_TYPES, + help="Compare type for the l7rule {}" + ) + parser.add_argument( + '--invert', + action='store_true', + default=None, + help="Invert l7rule" + ) + parser.add_argument( + '--value', + metavar='', + help="Rule value" + ) + parser.add_argument( + '--key', + metavar='', + help="Key for the l7rule" + ) + parser.add_argument( + '--type', + metavar='', + choices=TYPES, + help="Type for the l7rule {}" + ) + admin_group = parser.add_mutually_exclusive_group() + admin_group.add_argument( + '--enable', + action='store_true', + default=None, + help="Enable l7policy (default)" + ) + admin_group.add_argument( + '--disable', + action='store_true', + default=None, + help="Disable l7policy" + ) + + return parser + + def take_action(self, parsed_args): + attrs = v2_utils.get_l7rule_attrs(self.app.client_manager, parsed_args) + v2_utils.check_l7rule_attrs(attrs) + + l7policy_id = attrs.pop('l7policy_id') + l7rule_id = attrs.pop('l7rule_id') + + body = {'rule': attrs} + + self.app.client_manager.load_balancer.l7rule_set( + l7rule_id=l7rule_id, + l7policy_id=l7policy_id, + json=body + ) diff --git a/octaviaclient/osc/v2/utils.py b/octaviaclient/osc/v2/utils.py index 4de09e3..5c4c0eb 100644 --- a/octaviaclient/osc/v2/utils.py +++ b/octaviaclient/osc/v2/utils.py @@ -29,6 +29,7 @@ def get_resource_id(resource, resource_name, name): The UUID of the found resource """ try: + # Projects can be non-uuid so we need to account for this if resource_name == 'project': if name != 'non-uuid': project_id = identity_common.find_project( @@ -50,6 +51,11 @@ def get_resource_id(resource, resource_name, name): raise exceptions.CommandError(msg) else: return names[0].get('id') + elif resource_name == 'l7rules': + names = [re for re in resource(name['l7policy_id'])['rules'] + if re.get('id') == name['l7rule_id']] + name = name['l7rule_id'] + return names[0].get('id') else: names = [re for re in resource()[resource_name] if re.get('name') == name or re.get('id') == name] @@ -285,6 +291,52 @@ def check_l7policy_attrs(attrs): raise exceptions.CommandError(msg) +def get_l7rule_attrs(client_manager, parsed_args): + attr_map = { + 'action': ('action', str.upper), + 'project': ( + 'project_id', + 'project', + client_manager.identity + ), + 'invert': ('invert', lambda x: True), + 'l7rule': ( + 'l7rule_id', + 'l7rules', + 'l7policy', # parent attr + client_manager.load_balancer.l7rule_list + ), + 'l7policy': ( + 'l7policy_id', + 'l7policies', + client_manager.load_balancer.l7policy_list + ), + 'value': ('value', str), + 'key': ('key', str), + 'type': ('type', str), + 'compare_type': ('compare_type', str.upper), + 'enable': ('admin_state_up', lambda x: True), + 'disable': ('admin_state_up', lambda x: False) + } + + _attrs = vars(parsed_args) + attrs = _map_attrs(_attrs, attr_map) + + return attrs + + +def check_l7rule_attrs(attrs): + msg = None + if 'type' in attrs.keys() and attrs['type'] == 'COOKIE': + if 'key' not in attrs: + msg = 'Missing argument: --type COOKIE requires --key ' + elif 'type' in attrs.keys() and attrs['type'] == 'HEADER': + if 'key' not in attrs: + msg = 'Missing argument: --type HEADER requires --key ' + if msg is not None: + raise exceptions.CommandError(msg) + + def format_list(data): return '\n'.join(i['id'] for i in data) diff --git a/octaviaclient/tests/unit/api/test_load_balancer.py b/octaviaclient/tests/unit/api/test_load_balancer.py index bd3627f..e27e4d0 100644 --- a/octaviaclient/tests/unit/api/test_load_balancer.py +++ b/octaviaclient/tests/unit/api/test_load_balancer.py @@ -29,6 +29,7 @@ FAKE_LI = uuidutils.generate_uuid() FAKE_PO = uuidutils.generate_uuid() FAKE_ME = uuidutils.generate_uuid() FAKE_L7PO = uuidutils.generate_uuid() +FAKE_L7RU = uuidutils.generate_uuid() LIST_LB_RESP = { @@ -60,6 +61,12 @@ LIST_L7PO_RESP = [ {'name': 'l72'}, ] +LIST_L7RU_RESP = { + 'rules': + [{'id': uuidutils.generate_uuid()}, + {'id': uuidutils.generate_uuid()}] +} + SINGLE_LB_RESP = {'loadbalancer': {'id': FAKE_LB, 'name': 'lb1'}} SINGLE_LB_UPDATE = {"loadbalancer": {"admin_state_up": False}} @@ -75,6 +82,9 @@ SINGLE_L7PO_UPDATE = {'l7policy': {'admin_state_up': False}} SINGLE_ME_RESP = {'member': {'id': FAKE_ME, 'name': 'mem1'}} SINGLE_ME_UPDATE = {"member": {"admin_state_up": False}} +SINGLE_L7RU_RESP = {'rule': {'id': FAKE_L7RU}} +SINGLE_L7RU_UPDATE = {'rule': {'admin_state_up': False}} + class TestLoadBalancerv2(utils.TestCase): @@ -332,3 +342,59 @@ class TestLoadBalancer(TestLoadBalancerv2): ) ret = self.api.l7policy_delete(FAKE_L7PO) self.assertEqual(200, ret.status_code) + + def test_list_l7rule_no_options(self): + self.requests_mock.register_uri( + 'GET', + FAKE_URL + 'l7policies/' + FAKE_L7PO + '/rules', + json=LIST_L7RU_RESP, + status_code=200, + ) + ret = self.api.l7rule_list(FAKE_L7PO) + self.assertEqual(LIST_L7RU_RESP, ret) + + def test_show_l7rule(self): + self.requests_mock.register_uri( + 'GET', + FAKE_URL + 'l7policies/' + FAKE_L7PO + '/rules/' + FAKE_L7RU, + json=SINGLE_L7RU_RESP, + status_code=200 + ) + ret = self.api.l7rule_show(FAKE_L7RU, FAKE_L7PO) + self.assertEqual(SINGLE_L7RU_RESP['rule'], ret) + + def test_create_l7rule(self): + self.requests_mock.register_uri( + 'POST', + FAKE_URL + 'l7policies/' + FAKE_L7PO + '/rules', + json=SINGLE_L7RU_RESP, + status_code=200 + ) + ret = self.api.l7rule_create(FAKE_L7PO, json=SINGLE_L7RU_RESP) + self.assertEqual(SINGLE_L7RU_RESP, ret) + + def test_set_l7rule(self): + self.requests_mock.register_uri( + 'PUT', + FAKE_URL + 'l7policies/' + FAKE_L7PO + '/rules/' + FAKE_L7RU, + json=SINGLE_L7RU_UPDATE, + status_code=200 + ) + ret = self.api.l7rule_set( + l7rule_id=FAKE_L7RU, + l7policy_id=FAKE_L7PO, + json=SINGLE_L7RU_UPDATE + ) + self.assertEqual(SINGLE_L7RU_UPDATE, ret) + + def test_delete_l7rule(self): + self.requests_mock.register_uri( + 'DELETE', + FAKE_URL + 'l7policies/' + FAKE_L7PO + '/rules/' + FAKE_L7RU, + status_code=200 + ) + ret = self.api.l7rule_delete( + l7rule_id=FAKE_L7RU, + l7policy_id=FAKE_L7PO + ) + self.assertEqual(200, ret.status_code) diff --git a/octaviaclient/tests/unit/osc/v2/fakes.py b/octaviaclient/tests/unit/osc/v2/fakes.py index 634a994..9d63982 100644 --- a/octaviaclient/tests/unit/osc/v2/fakes.py +++ b/octaviaclient/tests/unit/osc/v2/fakes.py @@ -194,3 +194,33 @@ class FakeL7Policy(object): loaded=True) return l7po + + +class FakeL7Rule(object): + """Fake one or more L7policy.""" + + @staticmethod + def create_one_l7rule(attrs=None): + attrs = attrs or {} + + l7ru_info = { + "created_at": "2017-05-04T18:46:35", + "compare_type": "ENDS_WITH", + "provisioning_status": "ACTIVE", + "invert": False, + "admin_state_up": True, + "value": ".example.com", + "key": None, + "project_id": str(uuid.uuid4()), + "type": "HOST_NAME", + "id": str(uuid.uuid4()), + "operating_status": "ONLINE" + } + + l7ru_info.update(attrs) + + l7ru = fakes.FakeResource( + info=copy.deepcopy(l7ru_info), + loaded=True) + + return l7ru diff --git a/octaviaclient/tests/unit/osc/v2/test_l7rule.py b/octaviaclient/tests/unit/osc/v2/test_l7rule.py new file mode 100644 index 0000000..f52252b --- /dev/null +++ b/octaviaclient/tests/unit/osc/v2/test_l7rule.py @@ -0,0 +1,239 @@ +# 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 copy +import mock + +from octaviaclient.osc.v2 import l7rule +from octaviaclient.tests.unit.osc.v2 import fakes as ru_fakes + +AUTH_TOKEN = "foobar" +AUTH_URL = "http://192.0.2.2" + + +class TestL7Policy(ru_fakes.TestLoadBalancerv2): + + _l7ru = ru_fakes.FakeL7Rule.create_one_l7rule() + _l7po = ru_fakes.FakeL7Policy.create_one_l7policy() + + columns = ( + 'id', + 'project_id', + 'provisioning_status', + 'compare_type', + 'type', + 'key', + 'value', + 'invert', + 'admin_state_up') + + datalist = ( + ( + _l7ru.id, + _l7ru.project_id, + _l7ru.provisioning_status, + _l7ru.compare_type, + _l7ru.type, + _l7ru.key, + _l7ru.value, + _l7ru.invert, + _l7ru.admin_state_up + ), + ) + + info = {'rules': [{ + "provisioning_status": _l7ru.provisioning_status, + "compare_type": _l7ru.compare_type, + "type": _l7ru.type, + "key": _l7ru.key, + "project_id": _l7ru.project_id, + "id": _l7ru.id, + "value": _l7ru.value, + 'l7rule_id': _l7ru.id, + 'l7policy_id': _l7po.id, + 'admin_state_up': _l7ru.admin_state_up, + 'invert': _l7ru.invert + }]} + po_info = {'l7policies': [{ + "listener_id": _l7po.listener_id, + "description": _l7po.description, + "admin_state_up": _l7po.admin_state_up, + "rules": _l7po.rules, + "provisioning_status": _l7po.provisioning_status, + "redirect_pool_id": _l7po.redirect_pool_id, + "action": _l7po.action, + "position": _l7po.position, + "project_id": _l7po.project_id, + "id": _l7po.id, + "name": _l7po.name + }]} + l7po_info = copy.deepcopy(po_info) + l7ru_info = copy.deepcopy(info) + + def setUp(self): + super(TestL7Policy, self).setUp() + self.l7ru_mock = self.app.client_manager.load_balancer.load_balancers + self.l7ru_mock.reset_mock() + + self.api_mock = mock.Mock() + self.api_mock.l7rule_list.return_value = self.l7ru_info + self.api_mock.l7pool_list.return_value = self.l7po_info + lb_client = self.app.client_manager + lb_client.load_balancer = self.api_mock + + +class TestL7RuleList(TestL7Policy): + + def setUp(self): + super(TestL7RuleList, self).setUp() + self.cmd = l7rule.ListL7Rule(self.app, None) + + @mock.patch('octaviaclient.osc.v2.utils.get_l7rule_attrs') + def test_l7rule_list_no_options(self, mock_attrs): + mock_attrs.return_value = self.l7ru_info['rules'][0] + arglist = [self._l7po.id] + verifylist = [('l7policy', self._l7po.id)] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + columns, data = self.cmd.take_action(parsed_args) + + self.api_mock.l7rule_list.assert_called_with(l7policy_id=self._l7po.id) + self.assertEqual(self.columns, columns) + self.assertEqual(self.datalist, tuple(data)) + + +class TestL7RuleDelete(TestL7Policy): + + def setUp(self): + super(TestL7RuleDelete, self).setUp() + self.cmd = l7rule.DeleteL7Rule(self.app, None) + + @mock.patch('octaviaclient.osc.v2.utils.get_l7rule_attrs') + def test_l7rule_delete(self, mock_attrs): + mock_attrs.return_value = self.l7ru_info['rules'][0] + arglist = [self._l7po.id, self._l7ru.id] + verifylist = [ + ('l7policy', self._l7po.id), + ('l7rule', self._l7ru.id) + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + self.cmd.take_action(parsed_args) + self.api_mock.l7rule_delete.assert_called_with( + l7rule_id=self._l7ru.id, + l7policy_id=self._l7po.id + ) + + +class TestL7RuleCreate(TestL7Policy): + + def setUp(self): + super(TestL7RuleCreate, self).setUp() + self.api_mock = mock.Mock() + self.api_mock.l7rule_create.return_value = { + 'rule': self.l7ru_info} + lb_client = self.app.client_manager + lb_client.load_balancer = self.api_mock + + self.cmd = l7rule.CreateL7Rule(self.app, None) + + @mock.patch('octaviaclient.osc.v2.utils.get_l7rule_attrs') + def test_l7rule_create(self, mock_attrs): + mock_attrs.return_value = { + 'l7policy_id': self._l7po.id, + 'compare-type': 'ENDS_WITH', + 'value': '.example.com', + 'type': 'HOST_NAME' + } + arglist = [self._l7po.id, + '--compare-type', 'ENDS_WITH', + '--value', '.example.com', + '--type', 'HOST_NAME'] + + verifylist = [ + ('l7policy', self._l7po.id), + ('compare_type', 'ENDS_WITH'), + ('value', '.example.com'), + ('type', 'HOST_NAME') + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + self.cmd.take_action(parsed_args) + self.api_mock.l7rule_create.assert_called_with( + l7policy_id=self._l7po.id, + json={'rule': { + 'compare-type': 'ENDS_WITH', + 'value': '.example.com', + 'type': 'HOST_NAME'} + }) + + +class TestL7RuleShow(TestL7Policy): + + def setUp(self): + super(TestL7RuleShow, self).setUp() + self.api_mock = mock.Mock() + self.api_mock.l7policy_list.return_value = self.l7po_info + self.api_mock.l7rule_list.return_value = self.l7ru_info + self.api_mock.l7rule_show.return_value = { + 'rule': self.l7ru_info['rules'][0]} + lb_client = self.app.client_manager + lb_client.load_balancer = self.api_mock + + self.cmd = l7rule.ShowL7Rule(self.app, None) + + def test_l7rule_show(self): + arglist = [self._l7po.id, self._l7ru.id] + verifylist = [ + ('l7policy', self._l7po.id), + ('l7rule', self._l7ru.id) + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + self.cmd.take_action(parsed_args) + self.api_mock.l7rule_show.assert_called_with( + l7rule_id=self._l7ru.id, + l7policy_id=self._l7po.id + ) + + +class TestL7RuleSet(TestL7Policy): + + def setUp(self): + super(TestL7RuleSet, self).setUp() + self.cmd = l7rule.SetL7Rule(self.app, None) + + @mock.patch('octaviaclient.osc.v2.utils.get_l7rule_attrs') + def test_l7rule_set(self, mock_attrs): + mock_attrs.return_value = { + 'admin_state_up': False, + 'l7policy_id': self._l7po.id, + 'l7rule_id': self._l7ru.id + } + arglist = [ + self._l7po.id, + self._l7ru.id, + '--disable' + ] + verifylist = [ + ('l7policy', self._l7po.id), + ('l7rule', self._l7ru.id), + ('disable', True) + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + self.cmd.take_action(parsed_args) + self.api_mock.l7rule_set.assert_called_with( + l7rule_id=self._l7ru.id, + l7policy_id=self._l7po.id, + json={'rule': {'admin_state_up': False}}) diff --git a/setup.cfg b/setup.cfg index 5b89d07..ffe9cf7 100644 --- a/setup.cfg +++ b/setup.cfg @@ -52,6 +52,11 @@ openstack.load_balancer.v2 = loadbalancer_l7policy_show = octaviaclient.osc.v2.l7policy:ShowL7Policy loadbalancer_l7policy_delete = octaviaclient.osc.v2.l7policy:DeleteL7Policy loadbalancer_l7policy_set = octaviaclient.osc.v2.l7policy:SetL7Policy + loadbalancer_l7rule_create = octaviaclient.osc.v2.l7rule:CreateL7Rule + loadbalancer_l7rule_list = octaviaclient.osc.v2.l7rule:ListL7Rule + loadbalancer_l7rule_show = octaviaclient.osc.v2.l7rule:ShowL7Rule + loadbalancer_l7rule_delete = octaviaclient.osc.v2.l7rule:DeleteL7Rule + loadbalancer_l7rule_set = octaviaclient.osc.v2.l7rule:SetL7Rule [build_sphinx] source-dir = doc/source