diff --git a/CHANGES.md b/CHANGES.md index e195094..3234aac 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,10 @@ # Changelog +## v1.1.0 + +* Update acos_client, which this pack depends on, version from v1.4.6 to v2.6.0 + or later to be able to compatible with ACOS version up to v5.2.1 (#20) + ## v1.0.0 * Drop Python 2.7 support. diff --git a/pack.yaml b/pack.yaml index 91b6043..a9b68b2 100644 --- a/pack.yaml +++ b/pack.yaml @@ -7,7 +7,7 @@ keywords: - load balancer - ADC - network -version: 1.0.0 +version: 1.1.0 author: Hiroyasu OHYAMA email: user.localhost2000@gmail.com python_versions: diff --git a/requirements.txt b/requirements.txt index 19ced54..75a4b9a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1 @@ -acos-client==1.4.6 +acos-client>=2.6.0,<3.0.0 diff --git a/tests/acos_base_action_test_case.py b/tests/acos_base_action_test_case.py index 70a99fe..8f4ae8f 100644 --- a/tests/acos_base_action_test_case.py +++ b/tests/acos_base_action_test_case.py @@ -1,4 +1,5 @@ import logging +import mock import yaml from st2tests.base import BaseActionTestCase @@ -31,3 +32,52 @@ def reset(self): 'error': [], 'critical': [], } + + def get_mock_session(self, resp_data): + """This returns mock instance of request.Session to inspect + whether sending requests from each test have expected destination endpoint + and expected parameters. + """ + ACOS_API_AUTH_PATH = [ + '/services/rest/v2.1/?format=json&method=authenticate', + '/axapi/v3/auth' + ] + self._sending_requests = [] + + def _save_sending_request(api_url, method, params): + self._sending_requests.append({ + 'url': api_url, + 'method': method, + 'params': params, + }) + + def _mock_sending_request(api_url, method, params): + mock_resp = mock.Mock() + if method == 'POST' and any([x in api_url for x in ACOS_API_AUTH_PATH]): + mock_resp.json.return_value = { + 'authresponse': {'signature': 'token'}, # This is mock value for ACOS v3.0 + 'session_id': 'token', # This is mock value for ACOS v2.1 + } + else: + mock_resp.json.return_value = resp_data + + # This saves what kind of request was send + _save_sending_request(api_url, method, params) + + return mock_resp + + def get_side_effect(api_url, **kwargs): + return _mock_sending_request(api_url, 'GET', kwargs) + + def post_side_effect(api_url, **kwargs): + return _mock_sending_request(api_url, 'POST', kwargs) + + def delete_side_effect(api_url, **kwargs): + return _mock_sending_request(api_url, 'DELETE', kwargs) + + mock_session = mock.Mock() + mock_session.get.side_effect = get_side_effect + mock_session.post.side_effect = post_side_effect + mock_session.delete.side_effect = delete_side_effect + + return mock_session diff --git a/tests/fixtures/full.yaml b/tests/fixtures/full.yaml index 504bfad..529fe57 100644 --- a/tests/fixtures/full.yaml +++ b/tests/fixtures/full.yaml @@ -1,12 +1,12 @@ --- appliance: - - target: appliance_hostname1 + target: appliance_acos_v2.1 userid: admin passwd: hoge api_version: v2.1 - - target: appliance_hostname2 + target: appliance_acos_v3.0 userid: admin passwd: fuga api_version: v3.0 diff --git a/tests/test_get_slb_server.py b/tests/test_get_slb_server.py index 0a9a54e..2631c51 100644 --- a/tests/test_get_slb_server.py +++ b/tests/test_get_slb_server.py @@ -28,7 +28,7 @@ def test_get_slb_server(self, mock_client): 'action': 'get', 'name': 'hoge', 'one_target': True, - 'appliance': 'appliance_hostname1', + 'appliance': 'appliance_acos_v2.1', } result = self.action.run(**params) diff --git a/tests/test_list_slb_servers.py b/tests/test_list_slb_servers.py index 4e118c1..d613657 100644 --- a/tests/test_list_slb_servers.py +++ b/tests/test_list_slb_servers.py @@ -50,7 +50,7 @@ def test_list_slb_specific_server(self, mock_client): 'action': 'get', 'name': 'hoge', 'one_target': False, - 'appliance': 'appliance_hostname1', + 'appliance': 'appliance_acos_v2.1', } result = self.action.run(**params) diff --git a/tests/test_slb_service_group.py b/tests/test_slb_service_group.py new file mode 100644 index 0000000..2956d22 --- /dev/null +++ b/tests/test_slb_service_group.py @@ -0,0 +1,248 @@ +import json +import mock + +from acos_base_action_test_case import ACOSBaseActionTestCase +from ax_action_runner import AXActionRunner +from urllib.parse import urlparse + +RESP_SUCCESS = {'response': {'status': 'success'}} + + +class TestSLBServiceGroup_v2_1(ACOSBaseActionTestCase): + __test__ = True + action_cls = AXActionRunner + + def setUp(self): + super(TestSLBServiceGroup_v2_1, self).setUp() + + self.action = self.get_action_instance(self._full_config) + self.action.logger.addHandler(self._log_handler) + + @mock.patch('acos_client.v21.axapi_http.Session') + def test_list_slb_service_group_for_acos(self, mock_session): + mock_session.return_value = self.get_mock_session(resp_data=RESP_SUCCESS) + + params = { + 'action': 'get', + 'object_path': 'slb.service_group', + 'one_target': True, + 'name': '', + 'appliance': 'appliance_acos_v2.1', + } + result = self.action.run(**params) + + # check action results + self.assertEqual(result, (True, RESP_SUCCESS)) + + # check sending request contents that acos_client, + # which stackstorm-acos depends on, sends. + self.assertEqual(len(self._sending_requests), 1) + + urlobj = urlparse(self._sending_requests[0]['url']) + self.assertEqual(urlobj.hostname, 'appliance_acos_v2.1') + self.assertIn('method=slb.service_group.search', urlobj.query) + self.assertEqual(self._sending_requests[0]['method'], 'POST') + + @mock.patch('acos_client.v21.axapi_http.Session') + def test_get_slb_service_group_for_acos(self, mock_session): + mock_session.return_value = self.get_mock_session(resp_data=RESP_SUCCESS) + + params = { + 'action': 'get', + 'object_path': 'slb.service_group', + 'one_target': True, + 'name': 'test-slb-service-group', + 'appliance': 'appliance_acos_v2.1', + } + result = self.action.run(**params) + + # check action results + self.assertEqual(result, (True, RESP_SUCCESS)) + + # check sending request contents that acos_client, + # which stackstorm-acos depends on, sends. + self.assertEqual(len(self._sending_requests), 1) + + urlobj = urlparse(self._sending_requests[0]['url']) + self.assertEqual(urlobj.hostname, 'appliance_acos_v2.1') + self.assertIn('method=slb.service_group.search', urlobj.query) + self.assertEqual(self._sending_requests[0]['params']['data'], json.dumps({ + "name": "test-slb-service-group" + })) + self.assertEqual(self._sending_requests[0]['method'], 'POST') + + @mock.patch('acos_client.v21.axapi_http.Session') + def test_delete_slb_service_group_for_acos(self, mock_session): + mock_session.return_value = self.get_mock_session(resp_data=RESP_SUCCESS) + + params = { + 'action': 'delete', + 'object_path': 'slb.service_group', + 'one_target': True, + 'name': 'test-slb-service-group', + 'appliance': 'appliance_acos_v2.1', + } + result = self.action.run(**params) + + # check action results + self.assertEqual(result, (True, RESP_SUCCESS)) + + # check sending request contents that acos_client, + # which stackstorm-acos depends on, sends. + urlobj = urlparse(self._sending_requests[0]['url']) + self.assertEqual(urlobj.hostname, 'appliance_acos_v2.1') + self.assertIn('method=slb.service_group.delete', urlobj.query) + self.assertEqual(self._sending_requests[0]['params']['data'], json.dumps({ + "name": "test-slb-service-group" + })) + self.assertEqual(self._sending_requests[0]['method'], 'POST') + + @mock.patch('acos_client.v21.axapi_http.Session') + def test_create_slb_service_group_for_acos(self, mock_session): + mock_session.return_value = self.get_mock_session(resp_data=RESP_SUCCESS) + + params = { + 'action': 'create', + 'object_path': 'slb.service_group', + 'one_target': True, + 'name': 'test-slb-service-group', + 'protocol': 'tcp', + 'lb_method': 'round-robin', + 'appliance': 'appliance_acos_v2.1', + } + result = self.action.run(**params) + + # check action results + self.assertEqual(result, (True, RESP_SUCCESS)) + + # check sending request contents that acos_client, + # which stackstorm-acos depends on, sends. + urlobj = urlparse(self._sending_requests[0]['url']) + self.assertEqual(urlobj.hostname, 'appliance_acos_v2.1') + self.assertIn('method=slb.service_group.create', urlobj.query) + self.assertEqual(self._sending_requests[0]['params']['data'], json.dumps({ + "service_group": { + "name": "test-slb-service-group", + "protocol": "tcp", + "lb_method": "round-robin" + } + })) + self.assertEqual(self._sending_requests[0]['method'], 'POST') + + +class TestSLBServiceGroup_v3_0(ACOSBaseActionTestCase): + __test__ = True + action_cls = AXActionRunner + + def setUp(self): + super(TestSLBServiceGroup_v3_0, self).setUp() + + self.action = self.get_action_instance(self._full_config) + self.action.logger.addHandler(self._log_handler) + + @mock.patch('acos_client.v30.axapi_http.Session') + def test_list_slb_service_group_for_acos(self, mock_session): + mock_session.return_value = self.get_mock_session(resp_data=RESP_SUCCESS) + + params = { + 'action': 'get', + 'object_path': 'slb.service_group', + 'one_target': True, + 'name': '', + 'appliance': 'appliance_acos_v3.0', + } + result = self.action.run(**params) + + # check action results + self.assertEqual(result, (True, RESP_SUCCESS)) + + # check sending request contents that acos_client, + # which stackstorm-acos depends on, sends. + self.assertEqual(len(self._sending_requests), 1) + + urlobj = urlparse(self._sending_requests[0]['url']) + self.assertEqual(urlobj.hostname, 'appliance_acos_v3.0') + self.assertEqual(urlobj.path, '/axapi/v3/slb/service-group/') + self.assertEqual(self._sending_requests[0]['method'], 'GET') + + @mock.patch('acos_client.v30.axapi_http.Session') + def test_get_slb_service_group_for_acos(self, mock_session): + mock_session.return_value = self.get_mock_session(resp_data=RESP_SUCCESS) + + params = { + 'action': 'get', + 'object_path': 'slb.service_group', + 'one_target': True, + 'name': 'test-slb-service-group', + 'appliance': 'appliance_acos_v3.0', + } + result = self.action.run(**params) + + # check action results + self.assertEqual(result, (True, RESP_SUCCESS)) + + # check sending request contents that acos_client, + # which stackstorm-acos depends on, sends. + self.assertEqual(len(self._sending_requests), 1) + + urlobj = urlparse(self._sending_requests[0]['url']) + self.assertEqual(urlobj.hostname, 'appliance_acos_v3.0') + self.assertEqual(urlobj.path, '/axapi/v3/slb/service-group/test-slb-service-group') + self.assertEqual(self._sending_requests[0]['method'], 'GET') + + @mock.patch('acos_client.v30.axapi_http.Session') + def test_delete_slb_service_group_for_acos(self, mock_session): + mock_session.return_value = self.get_mock_session(resp_data=RESP_SUCCESS) + + params = { + 'action': 'delete', + 'object_path': 'slb.service_group', + 'one_target': True, + 'name': 'test-slb-service-group', + 'appliance': 'appliance_acos_v3.0', + } + result = self.action.run(**params) + + # check action results + self.assertEqual(result, (True, RESP_SUCCESS)) + + # check sending request contents that acos_client, + # which stackstorm-acos depends on, sends. + urlobj = urlparse(self._sending_requests[0]['url']) + self.assertEqual(urlobj.hostname, 'appliance_acos_v3.0') + self.assertEqual(urlobj.path, '/axapi/v3/slb/service-group/test-slb-service-group') + self.assertEqual(self._sending_requests[0]['method'], 'DELETE') + + @mock.patch('acos_client.v30.axapi_http.Session') + def test_create_slb_service_group_for_acos(self, mock_session): + mock_session.return_value = self.get_mock_session(resp_data=RESP_SUCCESS) + + params = { + 'action': 'create', + 'object_path': 'slb.service_group', + 'one_target': True, + 'name': 'test-slb-service-group', + 'protocol': 'tcp', + 'lb_method': 'round-robin', + 'appliance': 'appliance_acos_v3.0', + } + result = self.action.run(**params) + + # check action results + self.assertEqual(result, (True, RESP_SUCCESS)) + + # check sending request contents that acos_client, + # which stackstorm-acos depends on, sends. + urlobj = urlparse(self._sending_requests[0]['url']) + self.assertEqual(urlobj.hostname, 'appliance_acos_v3.0') + self.assertEqual(urlobj.path, '/axapi/v3/slb/service-group/') + self.assertEqual(self._sending_requests[0]['params']['data'], json.dumps({ + "service-group": { + "name": "test-slb-service-group", + "protocol": "tcp", + "health-check-disable": 0, + "lb-method": "round-robin", + "stateless-auto-switch": 0 + } + })) + self.assertEqual(self._sending_requests[0]['method'], 'POST')