schema: Add fingerprint and TTL

Calculate fingerprint for schema in deterministic way. Send fingerprint
value together with schema. Send TTL with schema to inform client about
caching interval.

https://fedorahosted.org/freeipa/ticket/4739

Reviewed-By: Jan Cholasta <jcholast@redhat.com>
This commit is contained in:
David Kupka 2016-06-21 14:07:07 +02:00 committed by Jan Cholasta
parent f85c347f4d
commit 034a111972

View File

@ -7,6 +7,7 @@ import itertools
import sys
import six
import hashlib
from .baseldap import LDAPObject
from ipalib import errors
@ -18,6 +19,10 @@ from ipalib.plugable import Registry
from ipalib.text import _
from ipapython.version import API_VERSION
# Schema TTL sent to clients in response to schema call.
# Number of seconds before client should check for schema update.
SCHEMA_TTL = 7*24*3600 # default: 7 days
__doc__ = _("""
API Schema
""") + _("""
@ -690,6 +695,33 @@ class output_find(BaseParamSearch):
class schema(Command):
NO_CLI = True
@staticmethod
def _calculate_fingerprint(data):
"""
Returns fingerprint for schema
Behavior of this function can be changed at any time
given that it always generates identical fingerprint for
identical data (change in order of items in dict is
irelevant) and the risk of generating identical fingerprint
for different inputs is low.
"""
to_process = [data]
fingerprint = hashlib.sha1()
for entry in to_process:
if isinstance(entry, (list, tuple)):
for item in entry:
to_process.append(item)
elif isinstance(entry, dict):
for key in sorted(entry.keys()):
to_process.append(key)
to_process.append(entry[key])
else:
fingerprint.update(unicode(entry).encode('utf-8'))
return fingerprint.hexdigest()[:8]
def execute(self, *args, **kwargs):
commands = list(self.api.Object.command.search(**kwargs))
for command in commands:
@ -712,4 +744,8 @@ class schema(Command):
schema['classes'] = classes
schema['topics'] = topics
schema_fp = self._calculate_fingerprint(schema)
schema['fingerprint'] = schema_fp
schema['ttl'] = SCHEMA_TTL
return dict(result=schema)