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().

Change-Id: I34b12b96de3ea21beaf935ed8a9f6bae2fe0d0bc
Closes-Bug: 1461251
This commit is contained in:
Brant Knudson 2015-06-07 11:20:44 -05:00
parent aa9e413a6d
commit 97c2c690d8
9 changed files with 56 additions and 19 deletions

View File

@ -12,6 +12,9 @@
from oslo_utils import timeutils
from keystoneclient import utils
# The set of attributes common between the RevokeEvent
# and the dictionaries created from the token Data.
_NAMES = ['trust_id',
@ -75,11 +78,11 @@ 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,
subsecond=True)
event['expires_at'] = utils.isotime(self.expires_at,
subsecond=True)
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

@ -77,7 +77,7 @@ class DiscoveryBase(dict):
@updated.setter
def updated(self, value):
self.updated_str = timeutils.isotime(value)
self.updated_str = utils.isotime(value)
@utils.positional()
def add_link(self, href, rel='self', type=None):

View File

@ -16,6 +16,7 @@ import uuid
from oslo_utils import timeutils
from keystoneclient.fixture import exception
from keystoneclient import utils
class _Service(dict):
@ -112,7 +113,7 @@ class Token(dict):
@expires.setter
def expires(self, value):
self.expires_str = timeutils.isotime(value)
self.expires_str = utils.isotime(value)
@property
def issued_str(self):
@ -128,7 +129,7 @@ class Token(dict):
@issued.setter
def issued(self, value):
self.issued_str = timeutils.isotime(value)
self.issued_str = utils.isotime(value)
@property
def _user(self):

View File

@ -16,6 +16,7 @@ import uuid
from oslo_utils import timeutils
from keystoneclient.fixture import exception
from keystoneclient import utils
class _Service(dict):
@ -136,7 +137,7 @@ class Token(dict):
@expires.setter
def expires(self, value):
self.expires_str = timeutils.isotime(value, subsecond=True)
self.expires_str = utils.isotime(value, subsecond=True)
@property
def issued_str(self):
@ -152,7 +153,7 @@ class Token(dict):
@issued.setter
def issued(self, value):
self.issued_str = timeutils.isotime(value, subsecond=True)
self.issued_str = utils.isotime(value, subsecond=True)
@property
def _user(self):

View File

@ -169,6 +169,7 @@ from keystoneclient.common import cms
from keystoneclient import exceptions
from keystoneclient.middleware import memcache_crypt
from keystoneclient.openstack.common import memorycache
from keystoneclient import utils
# alternative middleware configuration in the main application's
@ -382,7 +383,7 @@ def confirm_token_not_expired(data):
utcnow = timeutils.utcnow()
if utcnow >= expires:
raise InvalidUserToken('Token authorization failed')
return timeutils.isotime(at=expires, subsecond=True)
return utils.isotime(at=expires, subsecond=True)
def _v3_to_v2_catalog(catalog):

View File

@ -43,6 +43,7 @@ from keystoneclient.middleware import auth_token
from keystoneclient.openstack.common import memorycache
from keystoneclient.tests.unit import client_fixtures
from keystoneclient.tests.unit import utils
from keystoneclient import utils as client_utils
EXPECTED_V2_DEFAULT_ENV_RESPONSE = {
@ -1684,10 +1685,10 @@ class TokenExpirationTest(BaseAuthTokenMiddlewareTest):
super(TokenExpirationTest, self).setUp()
self.now = timeutils.utcnow()
self.delta = datetime.timedelta(hours=1)
self.one_hour_ago = timeutils.isotime(self.now - self.delta,
subsecond=True)
self.one_hour_earlier = timeutils.isotime(self.now + self.delta,
subsecond=True)
self.one_hour_ago = client_utils.isotime(self.now - self.delta,
subsecond=True)
self.one_hour_earlier = client_utils.isotime(self.now + self.delta,
subsecond=True)
def create_v2_token_fixture(self, expires=None):
v2_fixture = {

View File

@ -19,6 +19,7 @@ from keystoneclient import access
from keystoneclient import httpclient
from keystoneclient.tests.unit import utils
from keystoneclient.tests.unit.v2_0 import client_fixtures
from keystoneclient import utils as client_utils
try:
import keyring # noqa
@ -124,7 +125,7 @@ class KeyringTest(utils.TestCase):
# set an expired token into the keyring
auth_ref = access.AccessInfo.factory(body=PROJECT_SCOPED_TOKEN)
expired = timeutils.utcnow() - datetime.timedelta(minutes=30)
auth_ref['token']['expires'] = timeutils.isotime(expired)
auth_ref['token']['expires'] = client_utils.isotime(expired)
self.memory_keyring.password = pickle.dumps(auth_ref)
# stub and check that a new token is received, so not using expired
@ -152,7 +153,7 @@ class KeyringTest(utils.TestCase):
# set an token into the keyring
auth_ref = access.AccessInfo.factory(body=PROJECT_SCOPED_TOKEN)
future = timeutils.utcnow() + datetime.timedelta(minutes=30)
auth_ref['token']['expires'] = timeutils.isotime(future)
auth_ref['token']['expires'] = client_utils.isotime(future)
self.memory_keyring.password = pickle.dumps(auth_ref)
# don't stub get_raw_token so will fail if authenticate happens

View File

@ -18,6 +18,7 @@ import logging
import sys
from oslo_utils import encodeutils
from oslo_utils import timeutils
import prettytable
import six
@ -336,3 +337,32 @@ class positional(object):
return func(*args, **kwargs)
return inner
_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

@ -10,11 +10,10 @@
# License for the specific language governing permissions and limitations
# under the License.
from oslo_utils import timeutils
from keystoneclient import base
from keystoneclient import exceptions
from keystoneclient.i18n import _
from keystoneclient import utils
class Trust(base.Resource):
@ -61,7 +60,7 @@ class TrustManager(base.CrudManager):
# Convert datetime.datetime expires_at to iso format string
if expires_at:
expires_str = timeutils.isotime(at=expires_at, subsecond=True)
expires_str = utils.isotime(at=expires_at, subsecond=True)
else:
expires_str = None