Add --utc flag to cron trigger create

The server should not be doing any translation of times. It should be
assumed that what is sent to the server is being sent as UTC. The
addition of the --utc flags facilitates this. If the --utc flag is
specified, then the --first-time passed is assumed to be already
UTC and will not undergo a conversion. If it is not passed, the
--first-time arg will be converted based on the the localtime of the
client, then sent as UTC.

Change-Id: I424d042d1cbdadae3aa14cd408d9f27d14823aef
Depends-On: Ifbd63d9e1f56085928bede22ce4f2954e1b38991
Closes-Bug: #1654218
This commit is contained in:
Brad P. Crochet 2017-03-03 14:12:36 -05:00
parent 8d3f0376e6
commit d1508e0991
2 changed files with 76 additions and 3 deletions

View File

@ -13,6 +13,8 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
# #
import datetime
import time
from osc_lib.command import command from osc_lib.command import command
@ -123,7 +125,9 @@ class Create(command.ShowOne):
parser.add_argument( parser.add_argument(
'--first-time', '--first-time',
type=str, type=str,
help="Date and time of the first execution", default=None,
help=("Date and time of the first execution. Time is treated as "
"local time unless --utc is also specified"),
metavar='<YYYY-MM-DD HH:MM>' metavar='<YYYY-MM-DD HH:MM>'
) )
parser.add_argument( parser.add_argument(
@ -132,6 +136,11 @@ class Create(command.ShowOne):
help="Number of wanted executions", help="Number of wanted executions",
metavar='<integer>' metavar='<integer>'
) )
parser.add_argument(
'--utc',
action='store_true',
help="All times specified should be treated as UTC"
)
return parser return parser
@ -142,19 +151,38 @@ class Create(command.ShowOne):
else: else:
return {} return {}
@staticmethod
def _convert_time_string_to_utc(time_string):
datetime_format = '%Y-%m-%d %H:%M'
the_time = time_string
if the_time:
the_time = datetime.datetime.strptime(
the_time, datetime_format)
the_second = time.mktime(the_time.timetuple())
the_utc_time = datetime.datetime.utcfromtimestamp(the_second)
the_time = the_utc_time.strftime(datetime_format)
return the_time
def take_action(self, parsed_args): def take_action(self, parsed_args):
mistral_client = self.app.client_manager.workflow_engine mistral_client = self.app.client_manager.workflow_engine
wf_input = self._get_file_content_or_dict(parsed_args.workflow_input) wf_input = self._get_file_content_or_dict(parsed_args.workflow_input)
wf_params = self._get_file_content_or_dict(parsed_args.params) wf_params = self._get_file_content_or_dict(parsed_args.params)
first_time = parsed_args.first_time
if not parsed_args.utc:
first_time = self._convert_time_string_to_utc(
parsed_args.first_time)
trigger = mistral_client.cron_triggers.create( trigger = mistral_client.cron_triggers.create(
parsed_args.name, parsed_args.name,
parsed_args.workflow_identifier, parsed_args.workflow_identifier,
wf_input, wf_input,
wf_params, wf_params,
parsed_args.pattern, parsed_args.pattern,
parsed_args.first_time, first_time,
parsed_args.count parsed_args.count
) )

View File

@ -14,7 +14,9 @@
# under the License. # under the License.
# #
import datetime
import mock import mock
import time
from mistralclient.api.v2 import cron_triggers from mistralclient.api.v2 import cron_triggers
from mistralclient.commands.v2 import cron_triggers as cron_triggers_cmd from mistralclient.commands.v2 import cron_triggers as cron_triggers_cmd
@ -37,11 +39,37 @@ TRIGGER = cron_triggers.CronTrigger(mock, TRIGGER_DICT)
class TestCLITriggersV2(base.BaseCommandTest): class TestCLITriggersV2(base.BaseCommandTest):
@mock.patch('mistralclient.commands.v2.cron_triggers.Create.'
'_convert_time_string_to_utc')
@mock.patch('argparse.open', create=True) @mock.patch('argparse.open', create=True)
def test_create(self, mock_open): def test_create(self, mock_open, mock_convert):
self.client.cron_triggers.create.return_value = TRIGGER self.client.cron_triggers.create.return_value = TRIGGER
mock_open.return_value = mock.MagicMock(spec=open) mock_open.return_value = mock.MagicMock(spec=open)
result = self.call(
cron_triggers_cmd.Create,
app_args=['my_trigger', 'flow1', '--pattern', '* * * * *',
'--params', '{}', '--count', '5', '--first-time',
'4242-12-20 13:37', '--utc']
)
mock_convert.assert_not_called()
self.assertEqual(
(
'my_trigger', 'flow1', {}, '* * * * *',
'4242-12-20 13:37', 5, '1', '1'
),
result[1]
)
@mock.patch('mistralclient.commands.v2.cron_triggers.Create.'
'_convert_time_string_to_utc')
@mock.patch('argparse.open', create=True)
def test_create_no_utc(self, mock_open, mock_convert):
self.client.cron_triggers.create.return_value = TRIGGER
mock_open.return_value = mock.MagicMock(spec=open)
mock_convert.return_value = '4242-12-20 18:37'
result = self.call( result = self.call(
cron_triggers_cmd.Create, cron_triggers_cmd.Create,
app_args=['my_trigger', 'flow1', '--pattern', '* * * * *', app_args=['my_trigger', 'flow1', '--pattern', '* * * * *',
@ -49,6 +77,9 @@ class TestCLITriggersV2(base.BaseCommandTest):
'4242-12-20 13:37'] '4242-12-20 13:37']
) )
mock_convert.assert_called_once_with('4242-12-20 13:37')
self.client.cron_triggers.create.assert_called_once_with(
'my_trigger', 'flow1', {}, {}, '* * * * *', '4242-12-20 18:37', 5)
self.assertEqual( self.assertEqual(
( (
'my_trigger', 'flow1', {}, '* * * * *', 'my_trigger', 'flow1', {}, '* * * * *',
@ -57,6 +88,20 @@ class TestCLITriggersV2(base.BaseCommandTest):
result[1] result[1]
) )
def test_convert_time_string_to_utc(self):
cmd = cron_triggers_cmd.Create(self.app, None)
utc_value = cmd._convert_time_string_to_utc('4242-12-20 13:37')
is_dst = time.daylight and time.localtime().tm_isdst > 0
utc_offset = - (time.altzone if is_dst else time.timezone)
expected_time = (datetime.datetime(
4242, 12, 20, 13, 37) - datetime.timedelta(
0, utc_offset)).strftime('%Y-%m-%d %H:%M')
self.assertEqual(expected_time, utc_value)
def test_list(self): def test_list(self):
self.client.cron_triggers.list.return_value = [TRIGGER] self.client.cron_triggers.list.return_value = [TRIGGER]