From 7d102080cfa3ac1fad5d0e7d7771e2435177e8ef Mon Sep 17 00:00:00 2001 From: Jude Cross Date: Wed, 10 May 2017 09:54:46 -0700 Subject: [PATCH] Add healthmonitor commands to client This patch implements the the create, delete, list, set, and show commands for healthmonitors within the openstack client. Change-Id: Ia30422398d1c614d860def5980369b93921c4f0b --- doc/source/data/lbaas.csv | 10 +- doc/source/usage/osc/v2/load-balancer.rst | 193 ++++++++++++ octaviaclient/api/constants.py | 4 +- octaviaclient/api/load_balancer_v2.py | 70 +++++ octaviaclient/osc/v2/constants.py | 28 ++ octaviaclient/osc/v2/health_monitor.py | 286 ++++++++++++++++++ octaviaclient/osc/v2/utils.py | 36 +++ .../tests/unit/api/test_load_balancer.py | 59 ++++ octaviaclient/tests/unit/osc/v2/fakes.py | 38 +++ .../tests/unit/osc/v2/test_health_monitor.py | 197 ++++++++++++ setup.cfg | 5 + 11 files changed, 919 insertions(+), 7 deletions(-) create mode 100644 octaviaclient/osc/v2/health_monitor.py create mode 100644 octaviaclient/tests/unit/osc/v2/test_health_monitor.py diff --git a/doc/source/data/lbaas.csv b/doc/source/data/lbaas.csv index ad0d46b..68f0cfa 100644 --- a/doc/source/data/lbaas.csv +++ b/doc/source/data/lbaas.csv @@ -1,8 +1,8 @@ -lbaas-healthmonitor-create,,LBaaS v2 Create a healthmonitor. -lbaas-healthmonitor-delete,,LBaaS v2 Delete a given healthmonitor. -lbaas-healthmonitor-list,,LBaaS v2 List healthmonitors that belong to a given tenant. -lbaas-healthmonitor-show,,LBaaS v2 Show information of a given healthmonitor. -lbaas-healthmonitor-update,,LBaaS v2 Update a given healthmonitor. +lbaas-healthmonitor-create,loadbalancer healthmonitor create,LBaaS v2 Create a healthmonitor. +lbaas-healthmonitor-delete,loadbalancer healthmonitor delete,LBaaS v2 Delete a given healthmonitor. +lbaas-healthmonitor-list,loadbalancer healthmonitor list,LBaaS v2 List healthmonitors that belong to a given tenant. +lbaas-healthmonitor-show,loadbalancer healthmonitor show,LBaaS v2 Show information of a given healthmonitor. +lbaas-healthmonitor-update,loadbalancer healthmonitor set,LBaaS v2 Update a given healthmonitor. lbaas-l7policy-create,loadbalancer l7policy create,LBaaS v2 Create L7 policy. lbaas-l7policy-delete,loadbalancer l7policy delete,LBaaS v2 Delete a given L7 policy. lbaas-l7policy-list,loadbalancer l7policy list,LBaaS v2 List L7 policies that belong to a given listener. diff --git a/doc/source/usage/osc/v2/load-balancer.rst b/doc/source/usage/osc/v2/load-balancer.rst index d71aa89..68837cc 100644 --- a/doc/source/usage/osc/v2/load-balancer.rst +++ b/doc/source/usage/osc/v2/load-balancer.rst @@ -1024,3 +1024,196 @@ loadbalancer l7rule delete .. describe:: l7rule to delete. + +============= +healthmonitor +============= + +loadbalancer healthmonitor list +------------------------------- + +List health monitors + +.. program:: loadbalancer healthmonitor list +.. code:: bash + + openstack loadbalancer healthmonitor list + +loadbalancer healthmonitor show +------------------------------- + +Show the details of a single health monitor + +.. program:: loadbalancer healthmonitor show +.. code:: bash + + openstack loadbalancer healthmonitor show + + +.. _loadbalancer_healthmonitor_show-health_monitor: +.. describe:: + + Name or UUID of the health monitor. + +loadbalancer healthmonitor create +--------------------------------- + +Create a health monitor + +.. program:: loadbalancer healthmonitor create +.. code:: bash + + openstack loadbalancer healthmonitor create + [--name ] + --delay + [--expected-codes ] + [--http_method {'GET','POST','DELETE','PUT'}] + --timeout + --max-retries + [--url-path ] + --type {'PING','HTTP','TCP','HTTPS'} + [--max-retries-down ] + [--project ] + [--enable | --disable] + + +.. option:: --name + + Set the health monitor name. + +.. option:: --delay + + Set the time in seconds, between sending probes to members. + +.. option:: --expected-codes + + Set the list of HTTP status codes expected in response from the member to declare it healthy. + +.. option:: --http_method {'GET','POST','DELETE','PUT'} + + Set the HTTP method that the health monitor uses for requests. + +.. option:: --timeout + + Set the maximum time, in seconds, that a monitor waits to connect before it times out. + This value must be less than the delay value. + +.. option:: --max-retries + + The number of successful checks before changing the operating status of the member to ONLINE. + +.. option:: --url-path + + Set the HTTP URL path of the request sent by the monitor to test the health of a backend member. + +.. option:: --type {'PING','HTTP','TCP','HTTPS'} + + Set the type of health monitor. + +.. option:: --max-retries-down + + Set the number of allowed check failures before changing the operating status of the member to ERROR. + +.. option:: --project + + Project to use for the health monitor (name or ID). + +.. option:: --enable + + Enable health monitor (default). + +.. option:: --disable + + Disable health monitor. + +.. _loadbalancer_healthmonitor_create-pool_id: +.. describe:: + + Set the pool for the health monitor (name or ID). + +loadbalancer healthmonitor set +------------------------------ + +Update a health monitor + +.. program:: loadbalancer healthmonitor set +.. code:: bash + + openstack loadbalancer healthmonitor set + [--name ] + [--delay ] + [--expected-codes ] + [--http_method {'GET','POST','DELETE','PUT'}] + [--timeout ] + [--max-retries ] + [--max-retries-down ] + [--url-path ] + [--type {'PING','HTTP','TCP','HTTPS'}] + [--enable | --disable] + + +.. option:: --name + + Set health monitor name. + +.. option:: --delay + + Set the time in seconds, between sending probes to members. + +.. option:: --expected-codes + + Set the list of HTTP status codes expected in response from the member to declare it healthy. + +.. option:: --http_method {'GET','POST','DELETE','PUT'} + + Set the HTTP method that the health monitor uses for requests. + +.. option:: --timeout + + Set the maximum time, in seconds, that a monitor waits to connect before it times out. + This value must be less than the delay value. + +.. option:: --max-retries + + The number of successful checks before changing the operating status of the member to ONLINE. + +.. option:: --max-retries-down + + Set the number of allowed check failures before changing the operating status of the member to ERROR. + +.. option:: --url-path + + Set the HTTP URL path of the request sent by the monitor to test the health of a backend member. + +.. option:: --type {'PING','HTTP','TCP','HTTPS'} + + Set the type of health monitor. + +.. option:: --enable + + Enable health monitor. + +.. option:: --disable + + Disable health monitor. + +.. _loadbalancer_healthmonitor_set-health_monitor: +.. describe:: + + Health monitor to update (name or ID). + +loadbalancer healthmonitor delete +--------------------------------- + +Delete a health monitor + +.. program:: loadbalancer healthmonitor delete +.. code:: bash + + openstack loadbalancer healthmonitor delete + + +.. _loadbalancer_healthmonitor_delete-health_monitor: +.. describe:: + + Health monitor to delete (name or ID). diff --git a/octaviaclient/api/constants.py b/octaviaclient/api/constants.py index 43989da..04bb5a6 100644 --- a/octaviaclient/api/constants.py +++ b/octaviaclient/api/constants.py @@ -23,8 +23,8 @@ BASE_SINGLE_POOL_URL = BASE_POOL_URL + '/{pool_id}' BASE_MEMBER_URL = BASE_SINGLE_POOL_URL + '/members' BASE_SINGLE_MEMBER_URL = BASE_MEMBER_URL + '/{member_id}' -BASE_MONITOR_URL = '/healthmonitors' -BASE_SINGLE_MONITOR_URL = '/healthmonitors/{uuid}' +BASE_HEALTH_MONITOR_URL = '/healthmonitors' +BASE_SINGLE_HEALTH_MONITOR_URL = BASE_HEALTH_MONITOR_URL + '/{uuid}' BASE_L7POLICY_URL = '/l7policies' BASE_SINGLE_L7POLICY_URL = BASE_L7POLICY_URL + '/{policy_uuid}' diff --git a/octaviaclient/api/load_balancer_v2.py b/octaviaclient/api/load_balancer_v2.py index 4c62d27..594077a 100644 --- a/octaviaclient/api/load_balancer_v2.py +++ b/octaviaclient/api/load_balancer_v2.py @@ -458,3 +458,73 @@ class APIv2(api.BaseAPI): response = self.create(url, method='PUT', **kwargs) return response + + def health_monitor_list(self, **kwargs): + """List all health monitors + + :param kwargs: + Parameters to filter on (not implemented) + :return: + A dict containing a list of health monitors + """ + url = const.BASE_HEALTH_MONITOR_URL + policy_list = self.list(url, **kwargs) + + return policy_list + + def health_monitor_create(self, **kwargs): + """Create a health monitor + + :param kwargs: + Parameters to create a health monitor with (expects json=) + :return: + A dict of the created health monitor's settings + """ + url = const.BASE_HEALTH_MONITOR_URL + health_monitor = self.create(url, **kwargs) + + return health_monitor + + def health_monitor_delete(self, health_monitor_id): + """Delete a health_monitor + + :param string health_monitor_id: + ID of of health monitor to delete + :return: + Response Code from the API + """ + url = const.BASE_SINGLE_HEALTH_MONITOR_URL.format( + uuid=health_monitor_id) + response = self.delete(url) + + return response + + def health_monitor_show(self, health_monitor_id): + """Show a health monitor's settings + + :param string health_monitor_id: + ID of the health monitor to show + :return: + Dict of the specified health monitor's settings + """ + url = const.BASE_HEALTH_MONITOR_URL + health_monitor = self.find(path=url, value=health_monitor_id) + + return health_monitor + + def health_monitor_set(self, health_monitor_id, **kwargs): + """Update a health monitor's settings + + :param health_monitor_id: + ID of the health monitor to update + :param kwargs: + A dict of arguments to update a l7policy + :return: + Response Code from the API + """ + url = const.BASE_SINGLE_HEALTH_MONITOR_URL.format( + uuid=health_monitor_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 d0d0d4a..86186fe 100644 --- a/octaviaclient/osc/v2/constants.py +++ b/octaviaclient/osc/v2/constants.py @@ -170,3 +170,31 @@ L7RULE_COLUMNS = ( 'value', 'invert', 'admin_state_up') + +MONITOR_ROWS = ( + 'project_id', + 'name', + 'admin_state_up', + 'pools', + 'created_at', + 'provisioning_status', + 'updated_at', + 'delay', + 'expected_codes', + 'max_retries', + 'http_method', + 'timeout', + 'max_retries_down', + 'url_path', + 'type', + 'id', + 'operating_status' +) + +MONITOR_COLUMNS = ( + 'id', + 'name', + 'project_id', + 'type', + 'admin_state_up', +) diff --git a/octaviaclient/osc/v2/health_monitor.py b/octaviaclient/osc/v2/health_monitor.py new file mode 100644 index 0000000..a01fd72 --- /dev/null +++ b/octaviaclient/osc/v2/health_monitor.py @@ -0,0 +1,286 @@ +# 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. +# + +"""Health Monitor 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 + +HTTP_METHODS = ['GET', 'POST', 'DELETE', 'PUT', 'HEAD', 'OPTIONS', 'PATCH', + 'CONNECT', 'TRACE'] + + +class CreateHealthMonitor(command.ShowOne): + """Create a health monitor""" + + def get_parser(self, prog_name): + parser = super(CreateHealthMonitor, self).get_parser(prog_name) + + parser.add_argument( + 'pool', + metavar='', + help="Pool for the health monitor (name or ID)" + ) + parser.add_argument( + '--name', + metavar='', + help="Set health monitor name" + ) + parser.add_argument( + '--delay', + metavar='', + required=True, + help="Delay for the health monitor" + ) + parser.add_argument( + '--expected-codes', + metavar='', + help="Expected response code to monitor for." + ) + parser.add_argument( + '--http_method', + metavar='', + choices=HTTP_METHODS, + help="HTTP method to use." + ) + parser.add_argument( + '--timeout', + metavar='', + required=True, + help="Timeout for the health monitor" + ) + parser.add_argument( + '--max-retries', + metavar='', + type=int, + choices=range(1, 10), + required=True, + help="The number of successful checks before changing the " + "operating status of the member to ONLINE." + ) + parser.add_argument( + '--url-path', + metavar='', + help="URL path to endpoint" + ) + parser.add_argument( + '--type', + metavar='', + required=True, + choices=['PING', 'HTTP', 'TCP', 'HTTPS'], + help="Protocol to use for the health monitor" + ) + parser.add_argument( + '--max-retries-down', + metavar='', + type=int, + choices=range(1, 10), + help="Maximum number of retires until the health monitor reports " + "down." + ) + admin_group = parser.add_mutually_exclusive_group() + admin_group.add_argument( + '--enable', + action='store_true', + default=True, + help="Enable health monitor (default)" + ) + admin_group.add_argument( + '--disable', + action='store_true', + default=None, + help="Disable health monitor" + ) + + return parser + + def take_action(self, parsed_args): + rows = const.MONITOR_ROWS + attrs = v2_utils.get_health_monitor_attrs(self.app.client_manager, + parsed_args) + body = {"healthmonitor": attrs} + data = self.app.client_manager.load_balancer.health_monitor_create( + json=body) + + formatters = {'pools': v2_utils.format_list} + + return (rows, + (utils.get_dict_properties(data['healthmonitor'], + rows, + formatters=formatters))) + + +class DeleteHealthMonitor(command.Command): + """Delete a health monitor""" + + def get_parser(self, prog_name): + parser = super(DeleteHealthMonitor, self).get_parser(prog_name) + + parser.add_argument( + 'health_monitor', + metavar='', + help="Health monitor to delete (name or ID)" + ) + + return parser + + def take_action(self, parsed_args): + attrs = v2_utils.get_health_monitor_attrs(self.app.client_manager, + parsed_args) + + health_monitor_id = attrs.pop('health_monitor_id') + + self.app.client_manager.load_balancer.health_monitor_delete( + health_monitor_id=health_monitor_id) + + +class ListHealthMonitor(lister.Lister): + """List health monitors""" + + def get_parser(self, prog_name): + parser = super(ListHealthMonitor, self).get_parser(prog_name) + + return parser + + def take_action(self, parsed_args): + columns = const.MONITOR_COLUMNS + attrs = v2_utils.get_health_monitor_attrs(self.app.client_manager, + parsed_args) + data = self.app.client_manager.load_balancer.health_monitor_list( + **attrs) + + formatters = {'pools': v2_utils.format_list} + return (columns, + (utils.get_dict_properties(s, columns, formatters=formatters) + for s in data['healthmonitors'])) + + +class ShowHealthMonitor(command.ShowOne): + """Show the details of a single health monitor""" + + def get_parser(self, prog_name): + parser = super(ShowHealthMonitor, self).get_parser(prog_name) + + parser.add_argument( + 'health_monitor', + metavar='', + help='Name or UUID of the health monitor' + ) + + return parser + + def take_action(self, parsed_args): + rows = const.MONITOR_ROWS + attrs = v2_utils.get_health_monitor_attrs(self.app.client_manager, + parsed_args) + + health_monitor_id = attrs.pop('health_monitor_id') + + data = self.app.client_manager.load_balancer.health_monitor_show( + health_monitor_id=health_monitor_id, + ) + formatters = {'pools': v2_utils.format_list} + + return (rows, + (utils.get_dict_properties(data, rows, formatters=formatters))) + + +class SetHealthMonitor(command.Command): + """Update a health monitor""" + + def get_parser(self, prog_name): + parser = super(SetHealthMonitor, self).get_parser(prog_name) + + parser.add_argument( + 'health_monitor', + metavar='', + help="Health monitor to update (name or ID)" + ) + parser.add_argument( + '--name', + metavar='', + help="Set health monitor name" + ) + parser.add_argument( + '--delay', + metavar='', + help="Set delay for the health monitor" + ) + parser.add_argument( + '--expected-codes', + metavar='', + help="Set expected response code to monitor for." + ) + parser.add_argument( + '--http_method', + metavar='', + choices=HTTP_METHODS, + help="Set HTTP method to use." + ) + parser.add_argument( + '--timeout', + metavar='', + help="Set the timeout for the health monitor" + ) + parser.add_argument( + '--max-retries', + metavar='', + type=int, + choices=range(1, 10), + help="Set the number of successful checks before changing the " + "operating status of the member to ONLINE." + ) + parser.add_argument( + '--max-retries-down', + metavar='', + type=int, + choices=range(1, 10), + help="Set the Maximum number of retires until the health monitor " + "reports down." + ) + parser.add_argument( + '--url-path', + metavar='', + help="Set the URL path to endpoint" + ) + admin_group = parser.add_mutually_exclusive_group() + admin_group.add_argument( + '--enable', + action='store_true', + default=None, + help="Enable health monitor (default)" + ) + admin_group.add_argument( + '--disable', + action='store_true', + default=None, + help="Disable health monitor" + ) + + return parser + + def take_action(self, parsed_args): + attrs = v2_utils.get_health_monitor_attrs(self.app.client_manager, + parsed_args) + + listener_id = attrs.pop('health_monitor_id') + + body = {'healthmonitor': attrs} + + self.app.client_manager.load_balancer.health_monitor_set( + listener_id, json=body) diff --git a/octaviaclient/osc/v2/utils.py b/octaviaclient/osc/v2/utils.py index 5c4c0eb..cade568 100644 --- a/octaviaclient/osc/v2/utils.py +++ b/octaviaclient/osc/v2/utils.py @@ -337,6 +337,42 @@ def check_l7rule_attrs(attrs): raise exceptions.CommandError(msg) +def get_health_monitor_attrs(client_manager, parsed_args): + attr_map = { + 'health_monitor': ( + 'health_monitor_id', + 'healthmonitors', + client_manager.load_balancer.health_monitor_list + ), + 'project': ( + 'project_id', + 'project', + client_manager.identity + ), + 'name': ('name', str), + 'pool': ( + 'pool_id', + 'pools', + client_manager.load_balancer.pool_list + ), + 'delay': ('delay', int), + 'expected_codes': ('expected_codes', str), + 'max_retries': ('max_retries', int), + 'http_method': ('http_method', str), + 'type': ('type', str), + 'timeout': ('timeout', int), + 'max_retries_down': ('max_retries_down', int), + 'url_path': ('url_path', str), + '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 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 e27e4d0..91fd0a2 100644 --- a/octaviaclient/tests/unit/api/test_load_balancer.py +++ b/octaviaclient/tests/unit/api/test_load_balancer.py @@ -30,6 +30,7 @@ FAKE_PO = uuidutils.generate_uuid() FAKE_ME = uuidutils.generate_uuid() FAKE_L7PO = uuidutils.generate_uuid() FAKE_L7RU = uuidutils.generate_uuid() +FAKE_HM = uuidutils.generate_uuid() LIST_LB_RESP = { @@ -67,6 +68,12 @@ LIST_L7RU_RESP = { {'id': uuidutils.generate_uuid()}] } +LIST_HM_RESP = { + 'healthmonitors': + [{'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}} @@ -85,6 +92,9 @@ SINGLE_ME_UPDATE = {"member": {"admin_state_up": False}} SINGLE_L7RU_RESP = {'rule': {'id': FAKE_L7RU}} SINGLE_L7RU_UPDATE = {'rule': {'admin_state_up': False}} +SINGLE_HM_RESP = {'healthmonitor': {'id': FAKE_ME}} +SINGLE_HM_UPDATE = {'healthmonitor': {'admin_state_up': False}} + class TestLoadBalancerv2(utils.TestCase): @@ -398,3 +408,52 @@ class TestLoadBalancer(TestLoadBalancerv2): l7policy_id=FAKE_L7PO ) self.assertEqual(200, ret.status_code) + + def test_list_health_monitor_no_options(self): + self.requests_mock.register_uri( + 'GET', + FAKE_URL + 'healthmonitors', + json=LIST_HM_RESP, + status_code=200, + ) + ret = self.api.health_monitor_list() + self.assertEqual(LIST_HM_RESP, ret) + + def test_show_health_monitor(self): + self.requests_mock.register_uri( + 'GET', + FAKE_URL + 'healthmonitors/' + FAKE_HM, + json=SINGLE_HM_RESP, + status_code=200 + ) + ret = self.api.health_monitor_show(FAKE_HM) + self.assertEqual(SINGLE_HM_RESP['healthmonitor'], ret) + + def test_create_health_monitor(self): + self.requests_mock.register_uri( + 'POST', + FAKE_URL + 'healthmonitors', + json=SINGLE_HM_RESP, + status_code=200 + ) + ret = self.api.health_monitor_create(json=SINGLE_HM_RESP) + self.assertEqual(SINGLE_HM_RESP, ret) + + def test_set_health_monitor(self): + self.requests_mock.register_uri( + 'PUT', + FAKE_URL + 'healthmonitors/' + FAKE_HM, + json=SINGLE_HM_UPDATE, + status_code=200 + ) + ret = self.api.health_monitor_set(FAKE_HM, json=SINGLE_HM_UPDATE) + self.assertEqual(SINGLE_HM_UPDATE, ret) + + def test_delete_health_monitor(self): + self.requests_mock.register_uri( + 'DELETE', + FAKE_URL + 'healthmonitors/' + FAKE_HM, + status_code=200 + ) + ret = self.api.health_monitor_delete(FAKE_HM) + 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 9d63982..d07da93 100644 --- a/octaviaclient/tests/unit/osc/v2/fakes.py +++ b/octaviaclient/tests/unit/osc/v2/fakes.py @@ -224,3 +224,41 @@ class FakeL7Rule(object): loaded=True) return l7ru + + +class FakeHM(object): + """Fake one or more L7policy.""" + + @staticmethod + def create_one_health_monitor(attrs=None): + attrs = attrs or {} + + hm_info = { + "project_id": uuid.uuid4().hex, + "name": 'hm-name-' + uuid.uuid4().hex, + "admin_state_up": True, + "pools": [ + { + "id": uuid.uuid4().hex + } + ], + "created_at": "2017-05-10T06:11:10", + "provisioning_status": "PENDING_CREATE", + "delay": 10, + "expected_codes": "200", + "max_retries": 2, + "http_method": "GET", + "timeout": 10, + "max_retries_down": 3, + "url_path": "/some/custom/path", + "type": "HTTP", + "id": uuid.uuid4().hex + } + + hm_info.update(attrs) + + hm = fakes.FakeResource( + info=copy.deepcopy(hm_info), + loaded=True) + + return hm diff --git a/octaviaclient/tests/unit/osc/v2/test_health_monitor.py b/octaviaclient/tests/unit/osc/v2/test_health_monitor.py new file mode 100644 index 0000000..5d72f5d --- /dev/null +++ b/octaviaclient/tests/unit/osc/v2/test_health_monitor.py @@ -0,0 +1,197 @@ +# 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 osc_lib import exceptions + +from octaviaclient.osc.v2 import health_monitor +from octaviaclient.tests.unit.osc.v2 import fakes as hm_fakes + +AUTH_TOKEN = "foobar" +AUTH_URL = "http://192.0.2.2" + + +class TestHealthMonitor(hm_fakes.TestLoadBalancerv2): + + _hm = hm_fakes.FakeHM.create_one_health_monitor() + + columns = ('id', 'name', 'project_id', 'type', 'admin_state_up') + + datalist = ( + ( + _hm.id, + _hm.name, + _hm.project_id, + _hm.type, + _hm.admin_state_up + ), + ) + + info = { + 'healthmonitors': + [{ + "project_id": _hm.project_id, + "name": _hm.name, + "admin_state_up": True, + "pools": _hm.pools, + "created_at": _hm.created_at, + "delay": _hm.delay, + "expected_codes": _hm.expected_codes, + "max_retries": _hm.max_retries, + "http_method": _hm.http_method, + "timeout": _hm.timeout, + "max_retries_down": _hm.max_retries_down, + "url_path": _hm.url_path, + "type": _hm.type, + "id": _hm.id + }] + } + hm_info = copy.deepcopy(info) + + def setUp(self): + super(TestHealthMonitor, self).setUp() + self.li_mock = self.app.client_manager.load_balancer.load_balancers + self.li_mock.reset_mock() + + self.api_mock = mock.Mock() + self.api_mock.health_monitor_list.return_value = self.hm_info + lb_client = self.app.client_manager + lb_client.load_balancer = self.api_mock + + +class TestHealthMonitorList(TestHealthMonitor): + + def setUp(self): + super(TestHealthMonitorList, self).setUp() + self.cmd = health_monitor.ListHealthMonitor(self.app, None) + + def test_health_monitor_list_no_options(self): + arglist = [] + verifylist = [] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + columns, data = self.cmd.take_action(parsed_args) + + self.api_mock.health_monitor_list.assert_called_with() + self.assertEqual(self.columns, columns) + self.assertEqual(self.datalist, tuple(data)) + + +class TestHealthMonitorDelete(TestHealthMonitor): + + def setUp(self): + super(TestHealthMonitorDelete, self).setUp() + self.cmd = health_monitor.DeleteHealthMonitor(self.app, None) + + def test_health_monitor_delete(self): + arglist = [self._hm.id] + verifylist = [ + ('health_monitor', self._hm.id) + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + self.cmd.take_action(parsed_args) + self.api_mock.health_monitor_delete.assert_called_with( + health_monitor_id=self._hm.id) + + def test_health_monitor_delete_failure(self): + arglist = ['unknown_hm'] + verifylist = [ + ('health_monitor', 'unknown_hm') + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + self.assertRaises(exceptions.CommandError, self.cmd.take_action, + parsed_args) + self.assertNotCalled(self.api_mock.health_monitor_delete) + + +class TestHealthMonitorCreate(TestHealthMonitor): + + def setUp(self): + super(TestHealthMonitorCreate, self).setUp() + self.api_mock = mock.Mock() + self.api_mock.health_monitor_create.return_value = { + 'healthmonitor': self.hm_info['healthmonitors'][0]} + lb_client = self.app.client_manager + lb_client.load_balancer = self.api_mock + + self.cmd = health_monitor.CreateHealthMonitor(self.app, None) + + @mock.patch('octaviaclient.osc.v2.utils.get_health_monitor_attrs') + def test_health_monitor_create(self, mock_client): + mock_client.return_value = self.hm_info['healthmonitors'][0] + arglist = ['mock_pool_id', + '--name', self._hm.name, + '--delay', str(self._hm.delay), + '--timeout', str(self._hm.timeout), + '--max-retries', str(self._hm.max_retries), + '--type', self._hm.type] + verifylist = [ + ('pool', 'mock_pool_id'), + ('name', self._hm.name), + ('delay', str(self._hm.delay)), + ('timeout', str(self._hm.timeout)), + ('max_retries', self._hm.max_retries), + ('type', self._hm.type) + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + self.cmd.take_action(parsed_args) + self.api_mock.health_monitor_create.assert_called_with( + json={'healthmonitor': self.hm_info['healthmonitors'][0]}) + + +class TestHealthMonitorShow(TestHealthMonitor): + + def setUp(self): + super(TestHealthMonitorShow, self).setUp() + self.api_mock = mock.Mock() + self.api_mock.health_monitor_list.return_value = self.hm_info + self.api_mock.health_monitor_show.return_value = { + 'healthmonitor': self.hm_info['healthmonitors'][0]} + lb_client = self.app.client_manager + lb_client.load_balancer = self.api_mock + + self.cmd = health_monitor.ShowHealthMonitor(self.app, None) + + def test_health_monitor_show(self): + arglist = [self._hm.id] + verifylist = [ + ('health_monitor', self._hm.id), + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + self.cmd.take_action(parsed_args) + self.api_mock.health_monitor_show.assert_called_with( + health_monitor_id=self._hm.id) + + +class TestHealthMonitorSet(TestHealthMonitor): + + def setUp(self): + super(TestHealthMonitorSet, self).setUp() + self.cmd = health_monitor.SetHealthMonitor(self.app, None) + + def test_health_monitor_set(self): + arglist = [self._hm.id, '--name', 'new_name'] + verifylist = [ + ('health_monitor', self._hm.id), + ('name', 'new_name') + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + self.cmd.take_action(parsed_args) + self.api_mock.health_monitor_set.assert_called_with( + self._hm.id, json={'healthmonitor': {'name': 'new_name'}}) diff --git a/setup.cfg b/setup.cfg index ffe9cf7..f1a5533 100644 --- a/setup.cfg +++ b/setup.cfg @@ -57,6 +57,11 @@ openstack.load_balancer.v2 = loadbalancer_l7rule_show = octaviaclient.osc.v2.l7rule:ShowL7Rule loadbalancer_l7rule_delete = octaviaclient.osc.v2.l7rule:DeleteL7Rule loadbalancer_l7rule_set = octaviaclient.osc.v2.l7rule:SetL7Rule + loadbalancer_healthmonitor_create = octaviaclient.osc.v2.health_monitor:CreateHealthMonitor + loadbalancer_healthmonitor_list = octaviaclient.osc.v2.health_monitor:ListHealthMonitor + loadbalancer_healthmonitor_show = octaviaclient.osc.v2.health_monitor:ShowHealthMonitor + loadbalancer_healthmonitor_delete = octaviaclient.osc.v2.health_monitor:DeleteHealthMonitor + loadbalancer_healthmonitor_set = octaviaclient.osc.v2.health_monitor:SetHealthMonitor [build_sphinx] source-dir = doc/source