| Index: appengine/config_service/services.py
|
| diff --git a/appengine/config_service/services.py b/appengine/config_service/services.py
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..1489b2fd9d17f8cb54659ef453b57216e20abfb8
|
| --- /dev/null
|
| +++ b/appengine/config_service/services.py
|
| @@ -0,0 +1,79 @@
|
| +# Copyright 2015 The Swarming Authors. All rights reserved.
|
| +# Use of this source code is governed by the Apache v2.0 license that can be
|
| +# found in the LICENSE file.
|
| +
|
| +"""Provides info about registered luci services."""
|
| +
|
| +from components import config
|
| +from components import net
|
| +from components import utils
|
| +
|
| +from google.appengine.ext import ndb
|
| +
|
| +from proto import service_config_pb2
|
| +import common
|
| +import storage
|
| +import validation
|
| +
|
| +
|
| +class DynamicMetadataError(Exception):
|
| + """Raised when a service metadata endpoint response is bad."""
|
| +
|
| +
|
| +@ndb.tasklet
|
| +def get_services_async():
|
| + """Returns a list of registered luci services.
|
| +
|
| + The list is stored in services/luci-config:services.cfg. Never returns None.
|
| + Cached.
|
| + """
|
| + cfg = yield storage.get_self_config_async(
|
| + common.SERVICES_REGISTRY_FILENAME, service_config_pb2.ServicesCfg)
|
| + raise ndb.Return(cfg.services or [])
|
| +
|
| +
|
| +@ndb.tasklet
|
| +def _get_service_async(service_id):
|
| + services = yield get_services()
|
| + for service in services:
|
| + if service.id == service_id:
|
| + raise ndb.Return(service)
|
| +
|
| +
|
| +def _dict_to_dynamic_metadata(data):
|
| + validation.validate_service_dynamic_metadata_blob(
|
| + data,
|
| + config.validation.Context.raise_on_error(exc_type=DynamicMetadataError))
|
| +
|
| + metadata = service_config_pb2.ServiceDynamicMetadata()
|
| + validation_meta = data.get('validation')
|
| + if validation_meta:
|
| + metadata.validation.url = validation_meta['url']
|
| + for p in validation_meta.get('patterns', []):
|
| + pattern = metadata.validation.patterns.add()
|
| + pattern.config_set=p['config_set']
|
| + pattern.path=p['path']
|
| + return metadata
|
| +
|
| +
|
| +@utils.memcache_async('service_metadata', ['service_id'], time=60)
|
| +def get_metadata_async(service_id):
|
| + """Returns service dynamic metadata.
|
| +
|
| + Memcaches results for 1 min. Never returns None.
|
| +
|
| + Raises:
|
| + DynamicMetadataError if metadata endpoint response is bad.
|
| + """
|
| + service = yield _get_service_async(service_id)
|
| + if service is None:
|
| + raise ValueError('Service "%s" not found', service_id)
|
| +
|
| + if not service.metadata_url:
|
| + raise ndb.Return(service_config_pb2.ServiceDynamicMetadata())
|
| +
|
| + try:
|
| + res = net.json_request_async(service.metadata_url)
|
| + except net.Error as ex:
|
| + raise DynamicMetadataError('Net error: %s' % ex.message)
|
| + raise ndb.Return(_dict_to_dynamic_metadata(res))
|
|
|