python-botocore/botocore/service.py
2015-10-08 11:16:07 -07:00

207 lines
7.5 KiB
Python

# Copyright (c) 2012-2013 Mitch Garnaat http://garnaat.org/
# Copyright 2012-2014 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"). You
# may not use this file except in compliance with the License. A copy of
# the License is located at
#
# http://aws.amazon.com/apache2.0/
#
# or in the "license" file accompanying this file. This file is
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
# ANY KIND, either express or implied. See the License for the specific
# language governing permissions and limitations under the License.
import logging
from .endpoint import EndpointCreator
from .operation import Operation
from .waiter import LegacyWaiter
from .exceptions import ServiceNotInRegionError, NoRegionError
from .exceptions import UnknownEndpointError
from .model import ServiceModel, OperationModel
from .translate import denormalize_waiters
logger = logging.getLogger(__name__)
NOT_SET = object()
class Service(object):
"""
A service, such as Elastic Compute Cloud (EC2).
:ivar api_version: A string containing the API version this service
is using.
:ivar name: The full name of the service.
:ivar service_name: The canonical name of the service.
:ivar regions: A dict where each key is a region name and the
optional value is an endpoint for that region.
:ivar protocols: A list of protocols supported by the service.
"""
WAITER_CLASS = LegacyWaiter
def __init__(self, session, provider, service_name,
path='/', port=None, api_version=None):
self.timestamp_format = 'iso8601'
sdata = session.get_service_data(
service_name,
api_version=None
)
self._model = ServiceModel(sdata)
self.__dict__.update(sdata)
self._operations_data = self.__dict__.pop('operations')
self._operations = None
self.session = session
self.provider = provider
self.path = path
self.port = port
self.cli_name = service_name
# The name the service was set with can be different
# than the endpoint prefix (for now). For example
# elb == service name,
# elasticloadbalancing == endpoint_prefix
# If we want to retrieve resources on disk, it will be
# grouped by the service name, so we need to expose this
# as an attribute for client obejcts.
self.service_name = service_name
self._signature_version = NOT_SET
# Not all services have a top level documentation key,
# so we'll add one if needed.
if 'documentation' not in self.__dict__:
self.documentation = ''
@property
def service_full_name(self):
return self._model.metadata['serviceFullName']
@property
def endpoint_prefix(self):
return self._model.metadata['endpointPrefix']
@property
def global_endpoint(self):
return self._model.metadata.get('globalEndpoint')
@property
def target_prefix(self):
return self._model.metadata['targetPrefix']
@property
def type(self):
return self._model.metadata['protocol']
@property
def api_version(self):
return self._model.metadata['apiVersion']
@property
def signature_version(self):
if self._signature_version is NOT_SET:
signature_version = self._model.metadata.get('signatureVersion')
self._signature_version = signature_version
return self._signature_version
@signature_version.setter
def signature_version(self, value):
self._signature_version = value
def _create_operation_objects(self):
logger.debug("Creating operation objects for: %s", self)
operations = []
for operation_name in self._operations_data:
data = self._operations_data[operation_name]
data['name'] = operation_name
model = self._model.operation_model(operation_name)
op = Operation(self, data, model)
operations.append(op)
return operations
def __repr__(self):
return 'Service(%s)' % self.endpoint_prefix
@property
def operations(self):
if self._operations is None:
self._operations = self._create_operation_objects()
return self._operations
def get_endpoint(self, region_name=None, is_secure=True,
endpoint_url=None, verify=None):
"""
Return the Endpoint object for this service in a particular
region.
:type region_name: str
:param region_name: The name of the region.
:type is_secure: bool
:param is_secure: True if you want the secure (HTTPS) endpoint.
:type endpoint_url: str
:param endpoint_url: You can explicitly override the default
computed endpoint name with this parameter. If this arg is
provided then neither ``region_name`` nor ``is_secure``
is used in building the final ``endpoint_url``.
``region_name`` can still be useful for services that require
a region name independent of the endpoint_url (for example services
that use Signature Version 4, which require a region name for
use in the signature calculation).
"""
resolver = self.session.get_component('endpoint_resolver')
region = self.session.get_config_variable('region')
event_emitter = self.session.get_component('event_emitter')
model = self._model
credentials = self.session.get_credentials()
user_agent= self.session.user_agent()
endpoint_creator = EndpointCreator(resolver, region, event_emitter,
credentials, user_agent)
return endpoint_creator.create_endpoint(self._model, region_name, is_secure,
endpoint_url, verify)
def get_operation(self, operation_name):
"""
Find an Operation object for a given operation_name. The name
provided can be the original camel case name, the Python name or
the CLI name.
:type operation_name: str
:param operation_name: The name of the operation.
"""
for operation in self.operations:
op_names = (operation.name, operation.py_name, operation.cli_name)
if operation_name in op_names:
return operation
return None
def get_waiter(self, waiter_name, endpoint):
try:
config = self._load_waiter_config()[waiter_name]
except Exception as e:
raise ValueError("Waiter does not exist: %s" % waiter_name)
operation = self.get_operation(config['operation'])
return self.WAITER_CLASS(waiter_name, operation, endpoint, config)
def _load_waiter_config(self):
loader = self.session.get_component('data_loader')
api_version = self.api_version
config = loader.load_data('aws/%s/%s.waiters' % (
self.service_name, api_version))
config = denormalize_waiters(config['waiters'])
return config
def get_service(session, service_name, provider, api_version=None):
"""
Return a Service object for a given provider name and service name.
:type service_name: str
:param service_name: The name of the service.
:type provider: Provider
:param provider: The Provider object associated with the session.
"""
logger.debug("Creating service object for: %s", service_name)
return Service(session, provider, service_name)