Switch from deprecated isotime

oslo_utils.timeutils.isotime() is deprecated as of 1.6 so we need
to stop using it.

The deprecation message says to use datetime.datetime.isoformat()
instead, but the format of the string generated by isoformat isn't
the same as the format of the string generated by isotime. The string
is used in tokens and other public APIs and we can't change it
without potentially breaking clients.

So the workaround is to copy the current implementation from
oslo_utils.timeutils.isotime() to keystone.common.utils.isotime().

Closes-Bug: 1461251

Change-Id: Icf821be8cd4ee7f52c1a3d89bfed302488c080f2
This commit is contained in:
Brant Knudson 2015-06-02 14:55:50 -05:00
parent f6c01dd167
commit 386054847e
16 changed files with 114 additions and 69 deletions

View File

@ -19,11 +19,11 @@ from oslo_config import cfg
from oslo_log import log
from oslo_serialization import jsonutils
from oslo_utils import importutils
from oslo_utils import timeutils
import six
from keystone.common import controller
from keystone.common import dependency
from keystone.common import utils
from keystone.common import wsgi
from keystone import config
from keystone.contrib import federation
@ -526,7 +526,7 @@ class Auth(controller.V3Controller):
for t in tokens:
expires = t['expires']
if not (expires and isinstance(expires, six.text_type)):
t['expires'] = timeutils.isotime(expires)
t['expires'] = utils.isotime(expires)
data = {'revoked': tokens}
json_data = jsonutils.dumps(data)
signed_text = cms.cms_sign_text(json_data,

View File

@ -27,6 +27,7 @@ from oslo_config import cfg
from oslo_log import log
from oslo_serialization import jsonutils
from oslo_utils import strutils
from oslo_utils import timeutils
import passlib.hash
import six
from six import moves
@ -469,3 +470,32 @@ class WhiteListedItemFilter(object):
if name not in self._whitelist:
raise KeyError
return self._data[name]
_ISO8601_TIME_FORMAT_SUBSECOND = '%Y-%m-%dT%H:%M:%S.%f'
_ISO8601_TIME_FORMAT = '%Y-%m-%dT%H:%M:%S'
def isotime(at=None, subsecond=False):
"""Stringify time in ISO 8601 format."""
# Python provides a similar instance method for datetime.datetime objects
# called isoformat(). The format of the strings generated by isoformat()
# have a couple of problems:
# 1) The strings generated by isotime are used in tokens and other public
# APIs that we can't change without a deprecation period. The strings
# generated by isoformat are not the same format, so we can't just
# change to it.
# 2) The strings generated by isoformat do not include the microseconds if
# the value happens to be 0. This will likely show up as random failures
# as parsers may be written to always expect microseconds, and it will
# parse correctly most of the time.
if not at:
at = timeutils.utcnow()
st = at.strftime(_ISO8601_TIME_FORMAT
if not subsecond
else _ISO8601_TIME_FORMAT_SUBSECOND)
tz = at.tzinfo.tzname(None) if at.tzinfo else 'UTC'
st += ('Z' if tz == 'UTC' else tz)
return st

View File

@ -31,6 +31,7 @@ xmldsig = importutils.try_import("saml2.xmldsig")
if not xmldsig:
xmldsig = importutils.try_import("xmldsig")
from keystone.common import utils
from keystone import exception
from keystone.i18n import _, _LE
from keystone.openstack.common import fileutils
@ -94,7 +95,7 @@ class SAMLGenerator(object):
expires_in = CONF.saml.assertion_expiration_time
now = timeutils.utcnow()
future = now + datetime.timedelta(seconds=expires_in)
return timeutils.isotime(future, subsecond=True)
return utils.isotime(future, subsecond=True)
def _create_status(self):
"""Create an object that represents a SAML Status.
@ -240,7 +241,7 @@ class SAMLGenerator(object):
"""
authn_statement = saml.AuthnStatement()
authn_statement.authn_instant = timeutils.isotime()
authn_statement.authn_instant = utils.isotime()
authn_statement.session_index = uuid.uuid4().hex
authn_statement.session_not_on_or_after = expiration_time
@ -277,7 +278,7 @@ class SAMLGenerator(object):
"""
assertion = saml.Assertion()
assertion.id = self.assertion_id
assertion.issue_instant = timeutils.isotime()
assertion.issue_instant = utils.isotime()
assertion.version = '2.0'
assertion.issuer = issuer
assertion.signature = signature
@ -305,7 +306,7 @@ class SAMLGenerator(object):
response = samlp.Response()
response.id = uuid.uuid4().hex
response.destination = recipient
response.issue_instant = timeutils.isotime()
response.issue_instant = utils.isotime()
response.version = '2.0'
response.issuer = issuer
response.status = status

View File

@ -21,6 +21,7 @@ from oslo_utils import timeutils
import six
from keystone.common import sql
from keystone.common import utils
from keystone.contrib.oauth1 import core
from keystone import exception
from keystone.i18n import _
@ -163,7 +164,7 @@ class OAuth1(object):
if token_duration:
now = timeutils.utcnow()
future = now + datetime.timedelta(seconds=token_duration)
expiry_date = timeutils.isotime(future, subsecond=True)
expiry_date = utils.isotime(future, subsecond=True)
ref = {}
ref['id'] = request_token_id
@ -225,7 +226,7 @@ class OAuth1(object):
if token_duration:
now = timeutils.utcnow()
future = now + datetime.timedelta(seconds=token_duration)
expiry_date = timeutils.isotime(future, subsecond=True)
expiry_date = utils.isotime(future, subsecond=True)
# add Access Token
ref = {}

View File

@ -13,6 +13,8 @@
from oslo_utils import timeutils
from six.moves import map
from keystone.common import utils
# The set of attributes common between the RevokeEvent
# and the dictionaries created from the token Data.
@ -101,10 +103,10 @@ class RevokeEvent(object):
if self.consumer_id is not None:
event['OS-OAUTH1:access_token_id'] = self.access_token_id
if self.expires_at is not None:
event['expires_at'] = timeutils.isotime(self.expires_at)
event['expires_at'] = utils.isotime(self.expires_at)
if self.issued_before is not None:
event['issued_before'] = timeutils.isotime(self.issued_before,
subsecond=True)
event['issued_before'] = utils.isotime(self.issued_before,
subsecond=True)
return event
def key_for_name(self, name):

View File

@ -18,6 +18,7 @@ from oslo_config import cfg
from oslo_utils import timeutils
import six
from keystone.common import utils
from keystone import exception
from keystone.tests import unit as tests
from keystone.tests.unit import test_backend
@ -67,13 +68,13 @@ class KvsToken(tests.TestCase, test_backend.TokenTests):
valid_token_ref = token_persistence.get_token(valid_token_id)
expired_token_ref = token_persistence.get_token(expired_token_id)
expected_user_token_list = [
(valid_token_id, timeutils.isotime(valid_token_ref['expires'],
subsecond=True)),
(expired_token_id, timeutils.isotime(expired_token_ref['expires'],
subsecond=True))]
(valid_token_id, utils.isotime(valid_token_ref['expires'],
subsecond=True)),
(expired_token_id, utils.isotime(expired_token_ref['expires'],
subsecond=True))]
self.assertEqual(expected_user_token_list, user_token_list)
new_expired_data = (expired_token_id,
timeutils.isotime(
utils.isotime(
(timeutils.utcnow() - expire_delta),
subsecond=True))
self._update_user_token_index_direct(user_key, expired_token_id,
@ -82,10 +83,10 @@ class KvsToken(tests.TestCase, test_backend.TokenTests):
user_id=user_id)
valid_token_ref_2 = token_persistence.get_token(valid_token_id_2)
expected_user_token_list = [
(valid_token_id, timeutils.isotime(valid_token_ref['expires'],
subsecond=True)),
(valid_token_id_2, timeutils.isotime(valid_token_ref_2['expires'],
subsecond=True))]
(valid_token_id, utils.isotime(valid_token_ref['expires'],
subsecond=True)),
(valid_token_id_2, utils.isotime(valid_token_ref_2['expires'],
subsecond=True))]
user_token_list = token_persistence.driver._store.get(user_key)
self.assertEqual(expected_user_token_list, user_token_list)
@ -94,10 +95,10 @@ class KvsToken(tests.TestCase, test_backend.TokenTests):
new_token_id, data = self.create_token_sample_data(user_id=user_id)
new_token_ref = token_persistence.get_token(new_token_id)
expected_user_token_list = [
(valid_token_id, timeutils.isotime(valid_token_ref['expires'],
subsecond=True)),
(new_token_id, timeutils.isotime(new_token_ref['expires'],
subsecond=True))]
(valid_token_id, utils.isotime(valid_token_ref['expires'],
subsecond=True)),
(new_token_id, utils.isotime(new_token_ref['expires'],
subsecond=True))]
user_token_list = token_persistence.driver._store.get(user_key)
self.assertEqual(expected_user_token_list, user_token_list)

View File

@ -19,6 +19,7 @@ from oslo_utils import timeutils
from six.moves import range
from testtools import matchers
from keystone.common import utils
from keystone.contrib import revoke
from keystone.contrib.revoke import model
from keystone import exception
@ -147,8 +148,8 @@ class RevokeTests(object):
def test_expired_events_removed_validate_token_success(self, mock_utcnow):
def _sample_token_values():
token = _sample_blank_token()
token['expires_at'] = timeutils.isotime(_future_time(),
subsecond=True)
token['expires_at'] = utils.isotime(_future_time(),
subsecond=True)
return token
now = datetime.datetime.utcnow()
@ -175,7 +176,7 @@ class RevokeTests(object):
def test_revoke_by_expiration_project_and_domain_fails(self):
user_id = _new_id()
expires_at = timeutils.isotime(_future_time(), subsecond=True)
expires_at = utils.isotime(_future_time(), subsecond=True)
domain_id = _new_id()
project_id = _new_id()
self.assertThat(

View File

@ -18,6 +18,7 @@ from oslo_config import cfg
from oslo_utils import timeutils
from keystone.common import dependency
from keystone.common import utils
from keystone import exception
from keystone.tests import unit as tests
from keystone.tests.unit.ksfixtures import database
@ -657,8 +658,8 @@ def create_v2_token():
return {
"access": {
"token": {
"expires": timeutils.isotime(timeutils.utcnow() +
FUTURE_DELTA),
"expires": utils.isotime(timeutils.utcnow() +
FUTURE_DELTA),
"issued_at": "2013-05-21T00:02:43.941473Z",
"tenant": {
"enabled": True,
@ -673,7 +674,7 @@ def create_v2_token():
SAMPLE_V2_TOKEN_EXPIRED = {
"access": {
"token": {
"expires": timeutils.isotime(CURRENT_DATE),
"expires": utils.isotime(CURRENT_DATE),
"issued_at": "2013-05-21T00:02:43.941473Z",
"tenant": {
"enabled": True,
@ -689,7 +690,7 @@ def create_v3_token():
return {
"token": {
'methods': [],
"expires_at": timeutils.isotime(timeutils.utcnow() + FUTURE_DELTA),
"expires_at": utils.isotime(timeutils.utcnow() + FUTURE_DELTA),
"issued_at": "2013-05-21T00:02:43.941473Z",
}
}
@ -697,7 +698,7 @@ def create_v3_token():
SAMPLE_V3_TOKEN_EXPIRED = {
"token": {
"expires_at": timeutils.isotime(CURRENT_DATE),
"expires_at": utils.isotime(CURRENT_DATE),
"issued_at": "2013-05-21T00:02:43.941473Z",
}
}

View File

@ -28,6 +28,7 @@ from testtools import matchers
from testtools import testcase
from keystone import auth
from keystone.common import utils
from keystone import exception
from keystone.policy.backends import rules
from keystone.tests import unit as tests
@ -1560,8 +1561,8 @@ class TestTokenRevokeApi(TestTokenRevokeById):
expected_status=200).json_body['events']
self.assertEqual(2, len(events))
future = timeutils.isotime(timeutils.utcnow() +
datetime.timedelta(seconds=1000))
future = utils.isotime(timeutils.utcnow() +
datetime.timedelta(seconds=1000))
events = self.get('/OS-REVOKE/events?since=%s' % (future),
expected_status=200).json_body['events']
@ -3921,9 +3922,9 @@ class TestAuthContext(tests.TestCase):
self.auth_context = auth.controllers.AuthContext()
def test_pick_lowest_expires_at(self):
expires_at_1 = timeutils.isotime(timeutils.utcnow())
expires_at_2 = timeutils.isotime(timeutils.utcnow() +
datetime.timedelta(seconds=10))
expires_at_1 = utils.isotime(timeutils.utcnow())
expires_at_2 = utils.isotime(timeutils.utcnow() +
datetime.timedelta(seconds=10))
# make sure auth_context picks the lowest value
self.auth_context['expires_at'] = expires_at_1
self.auth_context['expires_at'] = expires_at_2

View File

@ -17,6 +17,7 @@ from oslo_utils import timeutils
import six
from testtools import matchers
from keystone.common import utils
from keystone.contrib.revoke import model
from keystone.tests.unit import test_v3
from keystone.token import provider
@ -25,7 +26,7 @@ from keystone.token import provider
def _future_time_string():
expire_delta = datetime.timedelta(seconds=1000)
future_time = timeutils.utcnow() + expire_delta
return timeutils.isotime(future_time)
return utils.isotime(future_time)
class OSRevokeTests(test_v3.RestfulTestCase, test_v3.JsonHomeTestMixin):
@ -55,13 +56,13 @@ class OSRevokeTests(test_v3.RestfulTestCase, test_v3.JsonHomeTestMixin):
self.assertTrue(
before_time <= event_issued_before,
'invalid event issued_before time; %s is not later than %s.' % (
timeutils.isotime(event_issued_before, subsecond=True),
timeutils.isotime(before_time, subsecond=True)))
utils.isotime(event_issued_before, subsecond=True),
utils.isotime(before_time, subsecond=True)))
self.assertTrue(
event_issued_before <= after_time,
'invalid event issued_before time; %s is not earlier than %s.' % (
timeutils.isotime(event_issued_before, subsecond=True),
timeutils.isotime(after_time, subsecond=True)))
utils.isotime(event_issued_before, subsecond=True),
utils.isotime(after_time, subsecond=True)))
del (event['issued_before'])
self.assertEqual(sample, event)
@ -76,7 +77,7 @@ class OSRevokeTests(test_v3.RestfulTestCase, test_v3.JsonHomeTestMixin):
expires_at = provider.default_expire_time()
sample = self._blank_event()
sample['user_id'] = six.text_type(user_id)
sample['expires_at'] = six.text_type(timeutils.isotime(expires_at))
sample['expires_at'] = six.text_type(utils.isotime(expires_at))
before_time = timeutils.utcnow()
self.revoke_api.revoke_by_expiration(user_id, expires_at)
resp = self.get('/OS-REVOKE/events')

View File

@ -16,6 +16,7 @@ import uuid
from oslo_utils import timeutils
from keystone.common import config
from keystone.common import utils
from keystone import exception
from keystone.tests import unit as tests
from keystone.tests.unit import ksfixtures
@ -69,7 +70,7 @@ class TestPayloads(tests.TestCase):
def test_time_string_to_int_conversions(self):
payload_cls = token_formatters.BasePayload
expected_time_str = timeutils.isotime()
expected_time_str = utils.isotime()
time_obj = timeutils.parse_isotime(expected_time_str)
expected_time_int = (
(timeutils.normalize_time(time_obj) -
@ -86,7 +87,7 @@ class TestPayloads(tests.TestCase):
def test_unscoped_payload(self):
exp_user_id = uuid.uuid4().hex
exp_methods = ['password']
exp_expires_at = timeutils.isotime(timeutils.utcnow())
exp_expires_at = utils.isotime(timeutils.utcnow())
exp_audit_ids = [provider.random_urlsafe_str()]
payload = token_formatters.UnscopedPayload.assemble(
@ -104,7 +105,7 @@ class TestPayloads(tests.TestCase):
exp_user_id = uuid.uuid4().hex
exp_methods = ['password']
exp_project_id = uuid.uuid4().hex
exp_expires_at = timeutils.isotime(timeutils.utcnow())
exp_expires_at = utils.isotime(timeutils.utcnow())
exp_audit_ids = [provider.random_urlsafe_str()]
payload = token_formatters.ProjectScopedPayload.assemble(
@ -124,7 +125,7 @@ class TestPayloads(tests.TestCase):
exp_user_id = uuid.uuid4().hex
exp_methods = ['password']
exp_domain_id = uuid.uuid4().hex
exp_expires_at = timeutils.isotime(timeutils.utcnow())
exp_expires_at = utils.isotime(timeutils.utcnow())
exp_audit_ids = [provider.random_urlsafe_str()]
payload = token_formatters.DomainScopedPayload.assemble(
@ -144,7 +145,7 @@ class TestPayloads(tests.TestCase):
exp_user_id = uuid.uuid4().hex
exp_methods = ['password']
exp_domain_id = CONF.identity.default_domain_id
exp_expires_at = timeutils.isotime(timeutils.utcnow())
exp_expires_at = utils.isotime(timeutils.utcnow())
exp_audit_ids = [provider.random_urlsafe_str()]
payload = token_formatters.DomainScopedPayload.assemble(
@ -164,7 +165,7 @@ class TestPayloads(tests.TestCase):
exp_user_id = uuid.uuid4().hex
exp_methods = ['password']
exp_project_id = uuid.uuid4().hex
exp_expires_at = timeutils.isotime(timeutils.utcnow())
exp_expires_at = utils.isotime(timeutils.utcnow())
exp_audit_ids = [provider.random_urlsafe_str()]
exp_trust_id = uuid.uuid4().hex
@ -185,7 +186,7 @@ class TestPayloads(tests.TestCase):
def test_unscoped_payload_with_non_uuid_user_id(self):
exp_user_id = 'someNonUuidUserId'
exp_methods = ['password']
exp_expires_at = timeutils.isotime(timeutils.utcnow())
exp_expires_at = utils.isotime(timeutils.utcnow())
exp_audit_ids = [provider.random_urlsafe_str()]
payload = token_formatters.UnscopedPayload.assemble(
@ -203,7 +204,7 @@ class TestPayloads(tests.TestCase):
exp_user_id = 'someNonUuidUserId'
exp_methods = ['password']
exp_project_id = uuid.uuid4().hex
exp_expires_at = timeutils.isotime(timeutils.utcnow())
exp_expires_at = utils.isotime(timeutils.utcnow())
exp_audit_ids = [provider.random_urlsafe_str()]
payload = token_formatters.ProjectScopedPayload.assemble(
@ -223,7 +224,7 @@ class TestPayloads(tests.TestCase):
exp_user_id = uuid.uuid4().hex
exp_methods = ['password']
exp_project_id = 'someNonUuidProjectId'
exp_expires_at = timeutils.isotime(timeutils.utcnow())
exp_expires_at = utils.isotime(timeutils.utcnow())
exp_audit_ids = [provider.random_urlsafe_str()]
payload = token_formatters.ProjectScopedPayload.assemble(
@ -243,7 +244,7 @@ class TestPayloads(tests.TestCase):
exp_user_id = 'someNonUuidUserId'
exp_methods = ['password']
exp_domain_id = uuid.uuid4().hex
exp_expires_at = timeutils.isotime(timeutils.utcnow())
exp_expires_at = utils.isotime(timeutils.utcnow())
exp_audit_ids = [provider.random_urlsafe_str()]
payload = token_formatters.DomainScopedPayload.assemble(
@ -263,7 +264,7 @@ class TestPayloads(tests.TestCase):
exp_user_id = 'someNonUuidUserId'
exp_methods = ['password']
exp_project_id = uuid.uuid4().hex
exp_expires_at = timeutils.isotime(timeutils.utcnow())
exp_expires_at = utils.isotime(timeutils.utcnow())
exp_audit_ids = [provider.random_urlsafe_str()]
exp_trust_id = uuid.uuid4().hex
@ -285,7 +286,7 @@ class TestPayloads(tests.TestCase):
exp_user_id = uuid.uuid4().hex
exp_methods = ['password']
exp_project_id = 'someNonUuidProjectId'
exp_expires_at = timeutils.isotime(timeutils.utcnow())
exp_expires_at = utils.isotime(timeutils.utcnow())
exp_audit_ids = [provider.random_urlsafe_str()]
exp_trust_id = uuid.uuid4().hex
@ -306,7 +307,7 @@ class TestPayloads(tests.TestCase):
def test_federated_payload_with_non_uuid_ids(self):
exp_user_id = 'someNonUuidUserId'
exp_methods = ['password']
exp_expires_at = timeutils.isotime(timeutils.utcnow())
exp_expires_at = utils.isotime(timeutils.utcnow())
exp_audit_ids = [provider.random_urlsafe_str()]
exp_federated_info = {'group_ids': [{'id': 'someNonUuidGroupId'}],
'idp_id': uuid.uuid4().hex,

View File

@ -15,6 +15,7 @@
import datetime
import sys
from keystone.common import utils
from keystoneclient.common import cms
from oslo_config import cfg
from oslo_log import log
@ -205,7 +206,7 @@ class Auth(controller.V2Controller):
raise exception.Forbidden()
if ('expires' in trust_ref) and (trust_ref['expires']):
expiry = trust_ref['expires']
if expiry < timeutils.parse_isotime(timeutils.isotime()):
if expiry < timeutils.parse_isotime(utils.isotime()):
raise exception.Forbidden()
user_id = trust_ref['trustor_user_id']
trustor_user_ref = self.identity_api.get_user(
@ -463,7 +464,7 @@ class Auth(controller.V2Controller):
for t in tokens:
expires = t['expires']
if expires and isinstance(expires, datetime.datetime):
t['expires'] = timeutils.isotime(expires)
t['expires'] = utils.isotime(expires)
data = {'revoked': tokens}
json_data = jsonutils.dumps(data)
signed_text = cms.cms_sign_text(json_data,

View File

@ -22,6 +22,7 @@ from oslo_utils import timeutils
import six
from keystone.common import kvs
from keystone.common import utils
from keystone import exception
from keystone.i18n import _, _LE, _LW
from keystone import token
@ -106,7 +107,7 @@ class Token(token.persistence.Driver):
# concern about the backend, always store the value(s) in the
# index as the isotime (string) version so this is where the string is
# built.
expires_str = timeutils.isotime(data_copy['expires'], subsecond=True)
expires_str = utils.isotime(data_copy['expires'], subsecond=True)
self._set_key(ptk, data_copy)
user_id = data['user']['id']
@ -205,8 +206,8 @@ class Token(token.persistence.Driver):
'revocation list.'), data['id'])
return
revoked_token_data['expires'] = timeutils.isotime(expires,
subsecond=True)
revoked_token_data['expires'] = utils.isotime(expires,
subsecond=True)
revoked_token_data['id'] = data['id']
token_list = self._get_key_or_default(self.revocation_key, default=[])

View File

@ -21,6 +21,7 @@ from six.moves.urllib import parse
from keystone.common import controller as common_controller
from keystone.common import dependency
from keystone.common import utils
from keystone.contrib import federation
from keystone import exception
from keystone.i18n import _, _LE
@ -99,7 +100,7 @@ class V2TokenDataHelper(object):
expires = token_ref.get('expires', provider.default_expire_time())
if expires is not None:
if not isinstance(expires, six.text_type):
expires = timeutils.isotime(expires)
expires = utils.isotime(expires)
token_data = token_ref.get('token_data')
if token_data:
@ -393,10 +394,10 @@ class V3TokenDataHelper(object):
if not expires:
expires = provider.default_expire_time()
if not isinstance(expires, six.string_types):
expires = timeutils.isotime(expires, subsecond=True)
expires = utils.isotime(expires, subsecond=True)
token_data['expires_at'] = expires
token_data['issued_at'] = (issued_at or
timeutils.isotime(subsecond=True))
utils.isotime(subsecond=True))
def _populate_audit_info(self, token_data, audit_info=None):
if audit_info is None or isinstance(audit_info, six.string_types):

View File

@ -24,6 +24,7 @@ import six
from six.moves import map, urllib
from keystone.auth import plugins as auth_plugins
from keystone.common import utils as ks_utils
from keystone import exception
from keystone.i18n import _, _LI
from keystone.token import provider
@ -204,9 +205,9 @@ class TokenFormatter(object):
# rather than appearing in the payload, the creation time is encoded
# into the token format itself
created_at = TokenFormatter.creation_time(token)
created_at = timeutils.isotime(at=created_at, subsecond=True)
created_at = ks_utils.isotime(at=created_at, subsecond=True)
expires_at = timeutils.parse_isotime(expires_at)
expires_at = timeutils.isotime(at=expires_at, subsecond=True)
expires_at = ks_utils.isotime(at=expires_at, subsecond=True)
return (user_id, methods, audit_ids, domain_id, project_id, trust_id,
federated_info, created_at, expires_at)
@ -285,7 +286,7 @@ class BasePayload(object):
"""
time_object = datetime.datetime.utcfromtimestamp(int(time_int))
return timeutils.isotime(time_object)
return ks_utils.isotime(time_object)
@classmethod
def attempt_convert_uuid_hex_to_bytes(cls, value):

View File

@ -22,6 +22,7 @@ import six
from keystone import assignment
from keystone.common import controller
from keystone.common import dependency
from keystone.common import utils
from keystone.common import validation
from keystone import exception
from keystone.i18n import _
@ -81,7 +82,7 @@ class TrustV3(controller.V3Controller):
def _fill_in_roles(self, context, trust, all_roles):
if trust.get('expires_at') is not None:
trust['expires_at'] = (timeutils.isotime
trust['expires_at'] = (utils.isotime
(trust['expires_at'],
subsecond=True))
@ -243,7 +244,7 @@ class TrustV3(controller.V3Controller):
if 'roles' in trust:
del trust['roles']
if trust.get('expires_at') is not None:
trust['expires_at'] = (timeutils.isotime
trust['expires_at'] = (utils.isotime
(trust['expires_at'],
subsecond=True))
return TrustV3.wrap_collection(context, trusts)