Consistently round down timestamps
This is one of the ways we can prevent race conditions with backends that round
datetime objects or strings before persisting them.
Closes-Bug: 1622010
(cherry picked from commit 301b6a7bc7
)
Conflicts:
keystone/tests/unit/test_v3_auth.py: freezegun was added only in Newton
keystone/tests/unit/test_v3_os_revoke.py: minor conflict
In addition to cherry-pick, time.sleep() was added to several tests.
The tests assume that some time must pass between some operations.
In Newton and later this was done in other, unrelated commits and
freezegun was used. Freezegun cannot be used in Mitaka. Because of
that, time.sleep() was added at the same places where freezegun's
tick() is used in Newton.
Change-Id: I7c6d525dfb4ec13edb360a77b27422310d545305
This commit is contained in:
parent
f1d9c54ef0
commit
8d12ba3736
|
@ -522,7 +522,7 @@ def isotime(at=None, subsecond=False):
|
|||
# parse correctly most of the time.
|
||||
|
||||
if not at:
|
||||
at = timeutils.utcnow()
|
||||
at = timeutils.utcnow().replace(microsecond=0)
|
||||
st = at.strftime(_ISO8601_TIME_FORMAT
|
||||
if not subsecond
|
||||
else _ISO8601_TIME_FORMAT_SUBSECOND)
|
||||
|
|
|
@ -90,7 +90,7 @@ class RevokeEvent(object):
|
|||
self.expires_at = self.expires_at.replace(microsecond=0)
|
||||
|
||||
if self.revoked_at is None:
|
||||
self.revoked_at = timeutils.utcnow()
|
||||
self.revoked_at = timeutils.utcnow().replace(microsecond=0)
|
||||
if self.issued_before is None:
|
||||
self.issued_before = self.revoked_at
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
# under the License.
|
||||
|
||||
import random
|
||||
import time
|
||||
import uuid
|
||||
|
||||
from oslo_config import cfg
|
||||
|
@ -155,6 +156,14 @@ class AssignmentTestCase(test_v3.RestfulTestCase,
|
|||
resource_url=collection_url)
|
||||
|
||||
self.delete(member_url)
|
||||
|
||||
# NOTE(breton): the sleep below is required because time
|
||||
# in revocations and token was rounded down. In Newton
|
||||
# release freezegun is used for this purpose instead of
|
||||
# sleep. Freezegun cannot be used in Mitaka release, because
|
||||
# it was not in requirements when release happened.
|
||||
time.sleep(1)
|
||||
|
||||
r = self.get(collection_url)
|
||||
self.assertValidRoleListResponse(r, expected_length=0,
|
||||
resource_url=collection_url)
|
||||
|
@ -193,6 +202,14 @@ class AssignmentTestCase(test_v3.RestfulTestCase,
|
|||
resource_url=collection_url)
|
||||
|
||||
self.delete(member_url)
|
||||
|
||||
# NOTE(breton): the sleep below is required because time
|
||||
# in revocations and token was rounded down. In Newton
|
||||
# release freezegun is used for this purpose instead of
|
||||
# sleep. Freezegun cannot be used in Mitaka release, because
|
||||
# it was not in requirements when release happened.
|
||||
|
||||
time.sleep(1)
|
||||
r = self.get(collection_url)
|
||||
self.assertValidRoleListResponse(r, expected_length=0,
|
||||
resource_url=collection_url)
|
||||
|
@ -232,6 +249,14 @@ class AssignmentTestCase(test_v3.RestfulTestCase,
|
|||
resource_url=collection_url)
|
||||
|
||||
self.delete(member_url)
|
||||
|
||||
# NOTE(breton): the sleep below is required because time
|
||||
# in revocations and token was rounded down. In Newton
|
||||
# release freezegun is used for this purpose instead of
|
||||
# sleep. Freezegun cannot be used in Mitaka release, because
|
||||
# it was not in requirements when release happened.
|
||||
time.sleep(1)
|
||||
|
||||
r = self.get(collection_url)
|
||||
self.assertValidRoleListResponse(r, expected_length=0,
|
||||
resource_url=collection_url)
|
||||
|
@ -325,11 +350,25 @@ class AssignmentTestCase(test_v3.RestfulTestCase,
|
|||
headers={'x-subject-token': token},
|
||||
expected_status=http_client.OK)
|
||||
|
||||
# NOTE(breton): the sleep below is required because time
|
||||
# in revocations and token was rounded down. In Newton
|
||||
# release freezegun is used for this purpose instead of
|
||||
# sleep. Freezegun cannot be used in Mitaka release, because
|
||||
# it was not in requirements when release happened.
|
||||
time.sleep(1)
|
||||
|
||||
# revokes the grant from group on project.
|
||||
self.assignment_api.delete_grant(role_id=self.role['id'],
|
||||
project_id=self.project['id'],
|
||||
group_id=self.group['id'])
|
||||
|
||||
# NOTE(breton): the sleep below is required because time
|
||||
# in revocations and token was rounded down. In Newton
|
||||
# release freezegun is used for this purpose instead of
|
||||
# sleep. Freezegun cannot be used in Mitaka release, because
|
||||
# it was not in requirements when release happened.
|
||||
time.sleep(1)
|
||||
|
||||
# validates the same token again; it should not longer be valid.
|
||||
self.head('/auth/tokens',
|
||||
headers={'x-subject-token': token},
|
||||
|
@ -551,6 +590,14 @@ class AssignmentTestCase(test_v3.RestfulTestCase,
|
|||
self.delete(ud_entity['links']['assignment'])
|
||||
self.delete(gp_entity['links']['assignment'])
|
||||
self.delete(up_entity['links']['assignment'])
|
||||
|
||||
# NOTE(breton): the sleep below is required because time
|
||||
# in revocations and token was rounded down. In Newton
|
||||
# release freezegun is used for this purpose instead of
|
||||
# sleep. Freezegun cannot be used in Mitaka release, because
|
||||
# it was not in requirements when release happened.
|
||||
time.sleep(1)
|
||||
|
||||
r = self.get(collection_url)
|
||||
self.assertValidRoleAssignmentListResponse(
|
||||
r,
|
||||
|
@ -1414,6 +1461,14 @@ class AssignmentInheritanceTestCase(test_v3.RestfulTestCase,
|
|||
|
||||
# Delete indirect assignment
|
||||
self.delete(inherited_url)
|
||||
|
||||
# NOTE(breton): the sleep below is required because time
|
||||
# in revocations and token was rounded down. In Newton
|
||||
# release freezegun is used for this purpose instead of
|
||||
# sleep. Freezegun cannot be used in Mitaka release, because
|
||||
# it was not in requirements when release happened.
|
||||
time.sleep(1)
|
||||
|
||||
# Check the direct assignment exists, but the inherited one does not
|
||||
self.head(direct_url)
|
||||
self.head(inherited_url, expected_status=http_client.NOT_FOUND)
|
||||
|
|
|
@ -17,6 +17,7 @@ import datetime
|
|||
import itertools
|
||||
import json
|
||||
import operator
|
||||
import time
|
||||
import uuid
|
||||
|
||||
from keystoneclient.common import cms
|
||||
|
@ -2042,6 +2043,13 @@ class TestTokenRevokeById(test_v3.RestfulTestCase):
|
|||
'group_id': self.group1['id'],
|
||||
'role_id': self.role1['id']})
|
||||
|
||||
# NOTE(breton): the sleep below is required because time
|
||||
# in revocations and token was rounded down. In Newton
|
||||
# release freezegun is used for this purpose instead of
|
||||
# sleep. Freezegun cannot be used in Mitaka release, because
|
||||
# it was not in requirements when release happened.
|
||||
time.sleep(1)
|
||||
|
||||
user1_token = self.get_requested_token(
|
||||
self.build_authentication_request(
|
||||
user_id=self.user1['id'],
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import time
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_serialization import jsonutils
|
||||
from six.moves import range
|
||||
|
@ -213,6 +215,13 @@ class IdentityTestFilteredCase(filtering.FilterTests,
|
|||
user['name'] = '%my%name%'
|
||||
self.identity_api.update_user(user['id'], user)
|
||||
|
||||
# NOTE(breton): the sleep below is required because time
|
||||
# in revocations and token was rounded down. In Newton
|
||||
# release freezegun is used for this purpose instead of
|
||||
# sleep. Freezegun cannot be used in Mitaka release, because
|
||||
# it was not in requirements when release happened.
|
||||
time.sleep(1)
|
||||
|
||||
url_by_name = '/users?name=%my%name%'
|
||||
r = self.get(url_by_name, auth=self.auth)
|
||||
|
||||
|
|
|
@ -77,7 +77,7 @@ class OSRevokeTests(test_v3.RestfulTestCase, test_v3.JsonHomeTestMixin):
|
|||
sample = self._blank_event()
|
||||
sample['user_id'] = six.text_type(user_id)
|
||||
sample['expires_at'] = six.text_type(utils.isotime(expires_at))
|
||||
before_time = timeutils.utcnow()
|
||||
before_time = timeutils.utcnow().replace(microsecond=0)
|
||||
self.revoke_api.revoke_by_expiration(user_id, expires_at)
|
||||
resp = self.get('/OS-REVOKE/events')
|
||||
events = resp.json_body['events']
|
||||
|
@ -88,7 +88,7 @@ class OSRevokeTests(test_v3.RestfulTestCase, test_v3.JsonHomeTestMixin):
|
|||
project_id = uuid.uuid4().hex
|
||||
sample = dict()
|
||||
sample['project_id'] = six.text_type(project_id)
|
||||
before_time = timeutils.utcnow()
|
||||
before_time = timeutils.utcnow().replace(microsecond=0)
|
||||
self.revoke_api.revoke(
|
||||
revoke_model.RevokeEvent(project_id=project_id))
|
||||
|
||||
|
@ -101,7 +101,7 @@ class OSRevokeTests(test_v3.RestfulTestCase, test_v3.JsonHomeTestMixin):
|
|||
domain_id = uuid.uuid4().hex
|
||||
sample = dict()
|
||||
sample['domain_id'] = six.text_type(domain_id)
|
||||
before_time = timeutils.utcnow()
|
||||
before_time = timeutils.utcnow().replace(microsecond=0)
|
||||
self.revoke_api.revoke(
|
||||
revoke_model.RevokeEvent(domain_id=domain_id))
|
||||
|
||||
|
|
|
@ -96,7 +96,8 @@ def default_expire_time():
|
|||
|
||||
"""
|
||||
expire_delta = datetime.timedelta(seconds=CONF.token.expiration)
|
||||
return timeutils.utcnow() + expire_delta
|
||||
expires_at = timeutils.utcnow() + expire_delta
|
||||
return expires_at.replace(microsecond=0)
|
||||
|
||||
|
||||
def audit_info(parent_audit_id):
|
||||
|
|
Loading…
Reference in New Issue