From 2be2b431524a73a3d4ef28a623b3b4c2c4f3e0be Mon Sep 17 00:00:00 2001 From: Lingxian Kong Date: Fri, 27 Apr 2018 16:39:47 +1200 Subject: [PATCH] Functional test for creating function version Change-Id: Ia7a44943ba439425f81da1b6727c129a31590a72 Story: 2001829 Task: 14456 --- .../services/qinling_client.py | 48 +++++++++++++ .../tests/api/test_function_versions.py | 72 +++++++++++++++++++ qinling_tempest_plugin/tests/base.py | 28 ++++++++ 3 files changed, 148 insertions(+) create mode 100644 qinling_tempest_plugin/tests/api/test_function_versions.py diff --git a/qinling_tempest_plugin/services/qinling_client.py b/qinling_tempest_plugin/services/qinling_client.py index bda79746..75d581c0 100644 --- a/qinling_tempest_plugin/services/qinling_client.py +++ b/qinling_tempest_plugin/services/qinling_client.py @@ -84,6 +84,28 @@ class QinlingClient(client_base.QinlingClientBase): return resp, json.loads(resp.text) + def update_function(self, function_id, package_data=None, code=None, + entry=None): + headers = {'X-Auth-Token': self.auth_provider.get_token()} + + req_body = {} + if code: + req_body['code'] = json.dumps(code) + if entry: + req_body['entry'] = entry + + req_kwargs = { + 'headers': headers, + 'data': req_body + } + if package_data: + req_kwargs.update({'files': {'package': package_data}}) + + url_path = '%s/v1/functions/%s' % (self.base_url, function_id) + resp = requests.put(url_path, **req_kwargs) + + return resp, json.loads(resp.text) + def download_function(self, function_id): return self.get('/v1/functions/%s?download=true' % function_id, headers={}) @@ -121,3 +143,29 @@ class QinlingClient(client_base.QinlingClientBase): resp, body = self.post_json('jobs', req_body) return resp, body + + def create_function_version(self, function_id, description=None): + req_body = {} + if description is not None: + req_body['description'] = description + + resp, body = self.post_json( + 'functions/%s/versions' % function_id, + req_body + ) + + return resp, body + + def delete_function_version(self, function_id, version, + ignore_notfound=False): + try: + resp, _ = self.delete( + '/v1/functions/{id}/versions/{version}'.format( + id=function_id, version=version) + ) + return resp + except exceptions.NotFound: + if ignore_notfound: + pass + else: + raise diff --git a/qinling_tempest_plugin/tests/api/test_function_versions.py b/qinling_tempest_plugin/tests/api/test_function_versions.py new file mode 100644 index 00000000..60d6c674 --- /dev/null +++ b/qinling_tempest_plugin/tests/api/test_function_versions.py @@ -0,0 +1,72 @@ +# Copyright 2018 Catalyst IT Ltd +# +# 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. +from tempest.lib import decorators +from tempest.lib import exceptions + +from qinling_tempest_plugin.tests import base + + +class FunctionVersionsTest(base.BaseQinlingTest): + name_prefix = 'FunctionVersionsTest' + + def setUp(self): + super(FunctionVersionsTest, self).setUp() + + # Wait until runtime is available + self.await_runtime_available(self.runtime_id) + + @decorators.idempotent_id('ce630c59-a79d-4b2d-89af-c7c5c8f8bd3f') + def test_create(self): + function_id = self.create_function() + new_version = self.create_function_version(function_id) + + self.assertEqual(1, new_version) + + resp, body = self.client.get_resources( + 'functions/%s/versions' % function_id) + + self.assertEqual(200, resp.status) + self.assertIn( + new_version, + [v['version_number'] for v in body['function_versions']] + ) + + @decorators.idempotent_id('9da2d24c-2ce4-4e6f-9e44-74ef1b9ec3cc') + def test_create_function_no_change(self): + function_id = self.create_function() + self.create_function_version(function_id) + + self.assertRaises( + exceptions.Forbidden, + self.client.create_function_version, + function_id + ) + + @decorators.idempotent_id('6864d134-fbb9-4738-9721-b541c4362789') + def test_create_function_change(self): + function_id = self.create_function() + version_1 = self.create_function_version(function_id) + self.update_function_package(function_id, + "python/test_python_sleep.py") + version_2 = self.create_function_version(function_id) + + self.assertGreater(version_2, version_1) + + resp, body = self.client.get_resources( + 'functions/%s/versions' % function_id) + self.assertEqual(200, resp.status) + + numbers = [v['version_number'] for v in body['function_versions']] + self.assertIn(version_1, numbers) + self.assertIn(version_2, numbers) diff --git a/qinling_tempest_plugin/tests/base.py b/qinling_tempest_plugin/tests/base.py index 999eeef5..0de54f8d 100644 --- a/qinling_tempest_plugin/tests/base.py +++ b/qinling_tempest_plugin/tests/base.py @@ -144,6 +144,20 @@ class BaseQinlingTest(test.BaseTestCase): return function_id + def update_function_package(self, function_id, function_path): + package_path = self.create_package(name=function_path) + base_name, _ = os.path.splitext(package_path) + module_name = os.path.basename(base_name) + + with open(package_path, 'rb') as package_data: + resp, _ = self.client.update_function( + function_id, + package_data=package_data, + entry='%s.main' % module_name + ) + + self.assertEqual(200, resp.status_code) + def create_webhook(self): resp, body = self.client.create_webhook(self.function_id) self.assertEqual(201, resp.status) @@ -164,3 +178,17 @@ class BaseQinlingTest(test.BaseTestCase): job_id, ignore_notfound=True) return job_id + + def create_function_version(self, function_id=None): + if not function_id: + function_id = self.create_function() + + resp, body = self.client.create_function_version(function_id) + self.assertEqual(201, resp.status) + + version = body['version_number'] + + self.addCleanup(self.client.delete_function_version, function_id, + version, ignore_notfound=True) + + return version