212 lines
7.4 KiB
Python
212 lines
7.4 KiB
Python
# 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.
|
|
|
|
import etcd3gw
|
|
from tempest import config
|
|
from tempest.lib import decorators
|
|
from tempest.lib import exceptions
|
|
import tenacity
|
|
|
|
from qinling_tempest_plugin.tests import base
|
|
|
|
CONF = config.CONF
|
|
|
|
|
|
class FunctionVersionsTest(base.BaseQinlingTest):
|
|
name_prefix = 'FunctionVersionsTest'
|
|
|
|
def setUp(self):
|
|
super(FunctionVersionsTest, self).setUp()
|
|
|
|
# Wait until runtime is available
|
|
self.wait_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)
|
|
|
|
@decorators.idempotent_id('3f735ed4-64b0-4ec3-8bf2-507e38dcea19')
|
|
def test_create_admin_not_allowed(self):
|
|
"""test_create_admin_not_allowed
|
|
|
|
Even admin user can not create function version for normal user's
|
|
function.
|
|
"""
|
|
function_id = self.create_function()
|
|
|
|
self.assertRaises(
|
|
exceptions.NotFound,
|
|
self.admin_client.create_function_version,
|
|
function_id
|
|
)
|
|
|
|
@decorators.idempotent_id('78dc5552-fcb8-4b27-86f7-5f3d96143934')
|
|
def test_create_version_lock_failed(self):
|
|
"""test_create_version_lock_failed
|
|
|
|
Creating a function requires a lock. If qinling failed to acquire the
|
|
lock then an error would be returned after some retries.
|
|
|
|
In this test we acquire the lock manually, so that qinling will fail
|
|
to acquire the lock.
|
|
"""
|
|
function_id = self.create_function()
|
|
|
|
etcd3_client = etcd3gw.client(host=CONF.qinling.etcd_host,
|
|
port=CONF.qinling.etcd_port)
|
|
lock_id = "function_version_%s" % function_id
|
|
with etcd3_client.lock(id=lock_id):
|
|
self.assertRaises(
|
|
exceptions.ServerFault,
|
|
self.client.create_function_version,
|
|
function_id
|
|
)
|
|
|
|
@decorators.idempotent_id('43c06f41-d116-43a7-a61c-115f7591b22e')
|
|
def test_get_by_admin(self):
|
|
"""Admin user can get normal user's function version."""
|
|
function_id = self.create_function()
|
|
version = self.create_function_version(function_id)
|
|
|
|
resp, body = self.admin_client.get_function_version(function_id,
|
|
version)
|
|
|
|
self.assertEqual(200, resp.status)
|
|
self.assertEqual(version, body.get("version_number"))
|
|
|
|
@decorators.idempotent_id('e6b865d8-ffa8-4cfc-8afb-820c64f9b2af')
|
|
def test_get_all_by_admin(self):
|
|
"""Admin user can list normal user's function version."""
|
|
function_id = self.create_function()
|
|
version = self.create_function_version(function_id)
|
|
|
|
resp, body = self.admin_client.get_function_versions(function_id)
|
|
|
|
self.assertEqual(200, resp.status)
|
|
self.assertIn(
|
|
version,
|
|
[v['version_number'] for v in body['function_versions']]
|
|
)
|
|
|
|
@decorators.idempotent_id('0e70ef18-687c-4ce4-ae29-aee2f88b4b9c')
|
|
def test_delete(self):
|
|
function_id = self.create_function()
|
|
version = self.create_function_version(function_id)
|
|
|
|
resp = self.client.delete_function_version(function_id, version)
|
|
|
|
self.assertEqual(204, resp.status)
|
|
|
|
resp, body = self.client.get_function_versions(function_id)
|
|
|
|
self.assertEqual(200, resp.status)
|
|
self.assertNotIn(
|
|
version,
|
|
[v['version_number'] for v in body['function_versions']]
|
|
)
|
|
|
|
@decorators.idempotent_id('c6717e2e-e80a-43d9-a25b-84f4b7453c76')
|
|
def test_delete_by_admin(self):
|
|
"""test_delete_by_admin
|
|
|
|
Admin user can not delete normal user's function version.
|
|
"""
|
|
function_id = self.create_function()
|
|
version = self.create_function_version(function_id)
|
|
|
|
self.assertRaises(
|
|
exceptions.NotFound,
|
|
self.admin_client.delete_function_version,
|
|
function_id,
|
|
version
|
|
)
|
|
|
|
@decorators.idempotent_id('7898f89f-a490-42a3-8cf7-63cbd9543a06')
|
|
def test_detach(self):
|
|
"""Admin only operation."""
|
|
function_id = self.create_function()
|
|
version = self.create_function_version(function_id)
|
|
|
|
# Create execution to allocate worker
|
|
resp, _ = self.client.create_execution(
|
|
function_id, input='{"name": "Qinling"}', version=version
|
|
)
|
|
self.assertEqual(201, resp.status)
|
|
|
|
resp, body = self.admin_client.get_function_workers(function_id,
|
|
version=version)
|
|
self.assertEqual(200, resp.status)
|
|
self.assertEqual(1, len(body['workers']))
|
|
|
|
# Detach function version from workers
|
|
resp, _ = self.admin_client.detach_function(function_id,
|
|
version=version)
|
|
self.assertEqual(202, resp.status)
|
|
|
|
def _assert_workers():
|
|
resp, body = self.admin_client.get_function_workers(
|
|
function_id,
|
|
version=version
|
|
)
|
|
self.assertEqual(200, resp.status)
|
|
self.assertEqual(0, len(body['workers']))
|
|
|
|
r = tenacity.Retrying(
|
|
wait=tenacity.wait_fixed(1),
|
|
stop=tenacity.stop_after_attempt(5),
|
|
retry=tenacity.retry_if_exception_type(AssertionError)
|
|
)
|
|
r.call(_assert_workers)
|