Merge "Parse function alias when job is running"
This commit is contained in:
commit
05387ff01a
|
@ -152,5 +152,5 @@ class FunctionAliasesController(rest.RestController):
|
||||||
|
|
||||||
alias = db_api.update_function_alias(alias_name, **values)
|
alias = db_api.update_function_alias(alias_name, **values)
|
||||||
|
|
||||||
LOG.info("Alias updated.")
|
LOG.info("Alias %s updated.", alias_name)
|
||||||
return resources.FunctionAlias.from_db_obj(alias)
|
return resources.FunctionAlias.from_db_obj(alias)
|
||||||
|
|
|
@ -56,37 +56,37 @@ class JobsController(rest.RestController):
|
||||||
'Either function_alias or function_id must be provided.'
|
'Either function_alias or function_id must be provided.'
|
||||||
)
|
)
|
||||||
|
|
||||||
# Check the input params.
|
|
||||||
first_time, next_time, count = jobs.validate_job(params)
|
|
||||||
LOG.info("Creating %s, params: %s", self.type, params)
|
LOG.info("Creating %s, params: %s", self.type, params)
|
||||||
|
|
||||||
version = params.get('function_version', 0)
|
# Check the input params.
|
||||||
# if function_alias provided
|
first_time, next_time, count = jobs.validate_job(params)
|
||||||
function_alias = params.get('function_alias')
|
|
||||||
if function_alias:
|
|
||||||
alias_db = db_api.get_function_alias(function_alias)
|
|
||||||
function_id = alias_db.function_id
|
|
||||||
version = alias_db.function_version
|
|
||||||
params.update({'function_id': function_id,
|
|
||||||
'version': version})
|
|
||||||
|
|
||||||
with db_api.transaction():
|
version = params.get('function_version', 0)
|
||||||
|
function_alias = params.get('function_alias')
|
||||||
|
|
||||||
|
if function_alias:
|
||||||
|
# Check if the alias exists.
|
||||||
|
db_api.get_function_alias(function_alias)
|
||||||
|
else:
|
||||||
|
# Check the function(version) exists.
|
||||||
db_api.get_function(params['function_id'])
|
db_api.get_function(params['function_id'])
|
||||||
if version > 0:
|
if version > 0:
|
||||||
|
# Check if the version exists.
|
||||||
db_api.get_function_version(params['function_id'], version)
|
db_api.get_function_version(params['function_id'], version)
|
||||||
|
|
||||||
values = {
|
values = {
|
||||||
'name': params.get('name'),
|
'name': params.get('name'),
|
||||||
'pattern': params.get('pattern'),
|
'pattern': params.get('pattern'),
|
||||||
'first_execution_time': first_time,
|
'first_execution_time': first_time,
|
||||||
'next_execution_time': next_time,
|
'next_execution_time': next_time,
|
||||||
'count': count,
|
'count': count,
|
||||||
'function_id': params['function_id'],
|
'function_alias': function_alias,
|
||||||
'function_version': version,
|
'function_id': params.get("function_id"),
|
||||||
'function_input': params.get('function_input'),
|
'function_version': version,
|
||||||
'status': status.RUNNING
|
'function_input': params.get('function_input'),
|
||||||
}
|
'status': status.RUNNING
|
||||||
db_job = db_api.create_job(values)
|
}
|
||||||
|
db_job = db_api.create_job(values)
|
||||||
|
|
||||||
return resources.Job.from_db_obj(db_job)
|
return resources.Job.from_db_obj(db_job)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
# Copyright 2019 Catalyst Cloud 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.
|
||||||
|
|
||||||
|
"""Make function id nullable for jobs table
|
||||||
|
|
||||||
|
Revision ID: 007
|
||||||
|
Revises: 006
|
||||||
|
"""
|
||||||
|
|
||||||
|
revision = '007'
|
||||||
|
down_revision = '006'
|
||||||
|
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
op.alter_column(
|
||||||
|
'jobs',
|
||||||
|
'function_id',
|
||||||
|
existing_type=sa.String(length=36),
|
||||||
|
nullable=True
|
||||||
|
)
|
|
@ -73,7 +73,8 @@ class Job(model_base.QinlingSecureModelBase):
|
||||||
count = sa.Column(sa.Integer)
|
count = sa.Column(sa.Integer)
|
||||||
function_id = sa.Column(
|
function_id = sa.Column(
|
||||||
sa.String(36),
|
sa.String(36),
|
||||||
sa.ForeignKey(Function.id)
|
sa.ForeignKey(Function.id),
|
||||||
|
nullable=True
|
||||||
)
|
)
|
||||||
function = relationship('Function', back_populates="jobs")
|
function = relationship('Function', back_populates="jobs")
|
||||||
function_input = sa.Column(sa.String(255), nullable=True)
|
function_input = sa.Column(sa.String(255), nullable=True)
|
||||||
|
|
|
@ -98,8 +98,16 @@ def handle_job(engine_client):
|
||||||
|
|
||||||
for job in jobs_db:
|
for job in jobs_db:
|
||||||
job_id = job.id
|
job_id = job.id
|
||||||
func_id = job.function_id
|
func_alias = job.function_alias
|
||||||
func_version = job.function_version
|
|
||||||
|
if func_alias:
|
||||||
|
alias = db_api.get_function_alias(func_alias, insecure=True)
|
||||||
|
func_id = alias.function_id
|
||||||
|
func_version = alias.function_version
|
||||||
|
else:
|
||||||
|
func_id = job.function_id
|
||||||
|
func_version = job.function_version
|
||||||
|
|
||||||
LOG.debug("Processing job: %s, function: %s(version %s)", job_id,
|
LOG.debug("Processing job: %s, function: %s(version %s)", job_id,
|
||||||
func_id, func_version)
|
func_id, func_version)
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ class TestJobController(base.APITest):
|
||||||
db_function = self.create_function()
|
db_function = self.create_function()
|
||||||
self.function_id = db_function.id
|
self.function_id = db_function.id
|
||||||
|
|
||||||
def test_post(self):
|
def test_create_with_function(self):
|
||||||
body = {
|
body = {
|
||||||
'name': self.rand_name('job', prefix=self.prefix),
|
'name': self.rand_name('job', prefix=self.prefix),
|
||||||
'first_execution_time': str(
|
'first_execution_time': str(
|
||||||
|
@ -43,7 +43,7 @@ class TestJobController(base.APITest):
|
||||||
|
|
||||||
self.assertEqual(201, resp.status_int)
|
self.assertEqual(201, resp.status_int)
|
||||||
|
|
||||||
def test_post_with_version(self):
|
def test_create_with_version(self):
|
||||||
db_api.increase_function_version(self.function_id, 0)
|
db_api.increase_function_version(self.function_id, 0)
|
||||||
|
|
||||||
body = {
|
body = {
|
||||||
|
@ -58,13 +58,10 @@ class TestJobController(base.APITest):
|
||||||
self.assertEqual(201, resp.status_int)
|
self.assertEqual(201, resp.status_int)
|
||||||
self.assertEqual(1, resp.json.get('function_version'))
|
self.assertEqual(1, resp.json.get('function_version'))
|
||||||
|
|
||||||
def test_post_with_alias(self):
|
def test_create_with_alias(self):
|
||||||
db_api.increase_function_version(self.function_id, 0,
|
|
||||||
description="version 1")
|
|
||||||
name = self.rand_name(name="alias", prefix=self.prefix)
|
name = self.rand_name(name="alias", prefix=self.prefix)
|
||||||
body = {
|
body = {
|
||||||
'function_id': self.function_id,
|
'function_id': self.function_id,
|
||||||
'function_version': 1,
|
|
||||||
'name': name
|
'name': name
|
||||||
}
|
}
|
||||||
db_api.create_function_alias(**body)
|
db_api.create_function_alias(**body)
|
||||||
|
@ -79,9 +76,21 @@ class TestJobController(base.APITest):
|
||||||
resp = self.app.post_json('/v1/jobs', job_body)
|
resp = self.app.post_json('/v1/jobs', job_body)
|
||||||
|
|
||||||
self.assertEqual(201, resp.status_int)
|
self.assertEqual(201, resp.status_int)
|
||||||
self.assertEqual(1, resp.json.get('function_version'))
|
self.assertEqual(name, resp.json.get('function_alias'))
|
||||||
|
self.assertIsNone(resp.json.get('function_id'))
|
||||||
|
|
||||||
def test_post_without_required_params(self):
|
def test_create_with_invalid_alias(self):
|
||||||
|
body = {
|
||||||
|
'function_alias': 'fake_alias',
|
||||||
|
'first_execution_time': str(
|
||||||
|
datetime.utcnow() + timedelta(hours=1)),
|
||||||
|
}
|
||||||
|
|
||||||
|
resp = self.app.post_json('/v1/jobs', body, expect_errors=True)
|
||||||
|
|
||||||
|
self.assertEqual(404, resp.status_int)
|
||||||
|
|
||||||
|
def test_create_without_required_params(self):
|
||||||
resp = self.app.post(
|
resp = self.app.post(
|
||||||
'/v1/jobs',
|
'/v1/jobs',
|
||||||
params={},
|
params={},
|
||||||
|
@ -90,7 +99,7 @@ class TestJobController(base.APITest):
|
||||||
|
|
||||||
self.assertEqual(400, resp.status_int)
|
self.assertEqual(400, resp.status_int)
|
||||||
|
|
||||||
def test_post_pattern(self):
|
def test_create_pattern(self):
|
||||||
body = {
|
body = {
|
||||||
'name': self.rand_name('job', prefix=self.prefix),
|
'name': self.rand_name('job', prefix=self.prefix),
|
||||||
'function_id': self.function_id,
|
'function_id': self.function_id,
|
||||||
|
@ -107,7 +116,7 @@ class TestJobController(base.APITest):
|
||||||
res["next_execution_time"]
|
res["next_execution_time"]
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_post_both_pattern_and_first_execution_time(self):
|
def test_create_both_pattern_and_first_execution_time(self):
|
||||||
body = {
|
body = {
|
||||||
'name': self.rand_name('job', prefix=self.prefix),
|
'name': self.rand_name('job', prefix=self.prefix),
|
||||||
'function_id': self.function_id,
|
'function_id': self.function_id,
|
||||||
|
|
|
@ -203,12 +203,13 @@ class DbTestCase(BaseTest):
|
||||||
|
|
||||||
return function
|
return function
|
||||||
|
|
||||||
def create_job(self, function_id=None, **kwargs):
|
def create_job(self, function_id=None, function_alias=None, **kwargs):
|
||||||
if not function_id:
|
if not function_id and not function_alias:
|
||||||
function_id = self.create_function().id
|
function_id = self.create_function().id
|
||||||
|
|
||||||
job_params = {
|
job_params = {
|
||||||
'name': self.rand_name('job', prefix=self.prefix),
|
'name': self.rand_name('job', prefix=self.prefix),
|
||||||
|
'function_alias': function_alias,
|
||||||
'function_id': function_id,
|
'function_id': function_id,
|
||||||
# 'auth_enable' is disabled by default
|
# 'auth_enable' is disabled by default
|
||||||
'project_id': DEFAULT_PROJECT_ID,
|
'project_id': DEFAULT_PROJECT_ID,
|
||||||
|
|
|
@ -117,7 +117,7 @@ class TestPeriodics(base.DbTestCase):
|
||||||
|
|
||||||
now = datetime.utcnow()
|
now = datetime.utcnow()
|
||||||
db_job = self.create_job(
|
db_job = self.create_job(
|
||||||
function_id,
|
function_id=function_id,
|
||||||
status=status.RUNNING,
|
status=status.RUNNING,
|
||||||
next_execution_time=now,
|
next_execution_time=now,
|
||||||
count=2
|
count=2
|
||||||
|
@ -197,3 +197,40 @@ class TestPeriodics(base.DbTestCase):
|
||||||
db_execs = db_api.get_executions(function_id=function_id,
|
db_execs = db_api.get_executions(function_id=function_id,
|
||||||
function_version=1)
|
function_version=1)
|
||||||
self.assertEqual(2, len(db_execs))
|
self.assertEqual(2, len(db_execs))
|
||||||
|
|
||||||
|
@mock.patch('qinling.utils.jobs.get_next_execution_time')
|
||||||
|
def test_job_handler_with_alias(self, mock_next_time):
|
||||||
|
e_client = mock.Mock()
|
||||||
|
now = datetime.utcnow()
|
||||||
|
# It doesn't matter what's the returned value, but need to be in
|
||||||
|
# datetime type.
|
||||||
|
mock_next_time.return_value = now + timedelta(seconds=1)
|
||||||
|
|
||||||
|
# Create a alias for a function.
|
||||||
|
alias_name = self.rand_name(name="alias", prefix=self.prefix)
|
||||||
|
db_func = self.create_function()
|
||||||
|
function_id = db_func.id
|
||||||
|
db_api.create_function_alias(name=alias_name, function_id=function_id)
|
||||||
|
|
||||||
|
self.create_job(
|
||||||
|
function_alias=alias_name,
|
||||||
|
status=status.RUNNING,
|
||||||
|
next_execution_time=now,
|
||||||
|
)
|
||||||
|
|
||||||
|
periodics.handle_job(e_client)
|
||||||
|
context.set_ctx(self.ctx)
|
||||||
|
|
||||||
|
# Create function version 1 and update the alias.
|
||||||
|
db_api.increase_function_version(function_id, 0)
|
||||||
|
db_api.update_function_alias(alias_name, function_version=1)
|
||||||
|
|
||||||
|
periodics.handle_job(e_client)
|
||||||
|
context.set_ctx(self.ctx)
|
||||||
|
|
||||||
|
db_func = db_api.get_function(function_id)
|
||||||
|
self.assertEqual(1, db_func.count)
|
||||||
|
db_version = db_api.get_function_version(function_id, 1)
|
||||||
|
self.assertEqual(1, db_version.count)
|
||||||
|
db_execs = db_api.get_executions(function_id=function_id)
|
||||||
|
self.assertEqual(2, len(db_execs))
|
||||||
|
|
Loading…
Reference in New Issue