Adding some more constraints to cron trigger

* User was able to create some triggers
   with different names but the same first-time
   and count. Now it is fixed.

Closes-Bug: #1449514

Change-Id: Ifde94b2f183faad8c9a5bb8723f11945da5bc08a
This commit is contained in:
Nikolay Mahotkin 2015-05-25 12:51:07 +03:00
parent 2761222195
commit 7f4f19fbe1
5 changed files with 113 additions and 2 deletions

View File

@ -0,0 +1,46 @@
# Copyright 2015 OpenStack Foundation.
#
# 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.
"""cron_trigger_constraints
Revision ID: 003
Revises: 002
Create Date: 2015-05-25 13:09:50.190136
"""
# revision identifiers, used by Alembic.
revision = '003'
down_revision = '002'
from alembic import op
import sqlalchemy as sa
def upgrade():
op.add_column(
'cron_triggers_v2',
sa.Column('first_execution_time', sa.DateTime(), nullable=True)
)
op.drop_index('workflow_input_hash', table_name='cron_triggers_v2')
op.drop_index('workflow_input_hash_2', table_name='cron_triggers_v2')
op.create_unique_constraint(
None,
'cron_triggers_v2', [
'workflow_input_hash', 'workflow_name', 'pattern',
'project_id', 'workflow_params_hash', 'remaining_executions',
'first_execution_time'
]
)

View File

@ -793,6 +793,12 @@ def create_cron_trigger(values, session=None):
"Duplicate entry for cron trigger %s: %s"
% (cron_trigger.name, e.columns)
)
# TODO(nmakhotkin): Remove this 'except' after fixing
# https://bugs.launchpad.net/oslo.db/+bug/1458583.
except db_exc.DBError as e:
raise exc.DBDuplicateEntry(
"Duplicate entry for cron trigger: %s" % e
)
return cron_trigger

View File

@ -248,13 +248,19 @@ class CronTrigger(mb.MistralSecureModelBase):
sa.UniqueConstraint('name', 'project_id'),
sa.UniqueConstraint(
'workflow_input_hash', 'workflow_name', 'pattern', 'project_id',
'workflow_params_hash'
'workflow_params_hash', 'remaining_executions',
'first_execution_time'
)
)
id = mb.id_column()
name = sa.Column(sa.String(200))
pattern = sa.Column(sa.String(100))
pattern = sa.Column(
sa.String(100),
nullable=True,
default='0 0 30 2 0' # Set default to 'never'.
)
first_execution_time = sa.Column(sa.DateTime, nullable=True)
next_execution_time = sa.Column(sa.DateTime, nullable=False)
workflow_name = sa.Column(sa.String(80))
remaining_executions = sa.Column(sa.Integer)
@ -281,6 +287,7 @@ class CronTrigger(mb.MistralSecureModelBase):
def to_dict(self):
d = super(CronTrigger, self).to_dict()
mb.datetime_to_str(d, 'first_execution_time')
mb.datetime_to_str(d, 'next_execution_time')
return d

View File

@ -87,6 +87,7 @@ def create_cron_trigger(name, workflow_name, workflow_input,
values = {
'name': name,
'pattern': pattern,
'first_execution_time': first_time,
'next_execution_time': next_time,
'remaining_executions': count,
'workflow_name': workflow_name,

View File

@ -70,6 +70,57 @@ class TriggerServiceV2Test(base.DbTestCase):
self.assertEqual(datetime.datetime(2010, 8, 25, 0, 10), next_time)
def test_trigger_create_the_same_first_time_or_count(self):
t_s.create_cron_trigger(
'test',
self.wf.name,
{},
{},
'*/5 * * * *',
"4242-12-25 13:37",
2,
datetime.datetime(2010, 8, 25)
)
t_s.create_cron_trigger(
'test2',
self.wf.name,
{},
{},
'*/5 * * * *',
"4242-12-25 13:37",
4,
datetime.datetime(2010, 8, 25)
)
t_s.create_cron_trigger(
'test3',
self.wf.name,
{},
{},
'*/5 * * * *',
"5353-12-25 13:37",
2,
datetime.datetime(2010, 8, 25)
)
# Creations above should be ok.
# But creation with the same count and first time
# simultaneously leads to error.
self.assertRaises(
exc.DBDuplicateEntry,
t_s.create_cron_trigger,
'test4',
self.wf.name,
{},
{},
'*/5 * * * *',
"4242-12-25 13:37",
2,
None
)
def test_trigger_create_wrong_workflow_input(self):
wf_with_input = """---
version: '2.0'