OLD | NEW |
(Empty) | |
| 1 # Copyright 2016 Google Inc. All Rights Reserved. |
| 2 # |
| 3 # Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 # you may not use this file except in compliance with the License. |
| 5 # You may obtain a copy of the License at |
| 6 # |
| 7 # http://www.apache.org/licenses/LICENSE-2.0 |
| 8 # |
| 9 # Unless required by applicable law or agreed to in writing, software |
| 10 # distributed under the License is distributed on an "AS IS" BASIS, |
| 11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 # See the License for the specific language governing permissions and |
| 13 # limitations under the License. |
| 14 |
| 15 """Provides a method for fetching Service Configuration from Google Service |
| 16 Management API.""" |
| 17 |
| 18 |
| 19 import logging |
| 20 import json |
| 21 import os |
| 22 import urllib3 |
| 23 |
| 24 from apitools.base.py import encoding |
| 25 import google.api.gen.servicecontrol_v1_messages as messages |
| 26 from oauth2client import client |
| 27 from urllib3.contrib import appengine |
| 28 |
| 29 |
| 30 logger = logging.getLogger(__name__) |
| 31 |
| 32 _GOOGLE_API_SCOPE = "https://www.googleapis.com/auth/cloud-platform" |
| 33 |
| 34 _SERVICE_MGMT_URL_TEMPLATE = ("https://servicemanagement.googleapis.com" |
| 35 "/v1/services/{}/configs/{}") |
| 36 |
| 37 _SERVICE_NAME_ENV_KEY = "ENDPOINTS_SERVICE_NAME" |
| 38 _SERVICE_VERSION_ENV_KEY = "ENDPOINTS_SERVICE_VERSION" |
| 39 |
| 40 |
| 41 def fetch_service_config(service_name=None, service_version=None): |
| 42 """Fetches the service config from Google Serivce Management API. |
| 43 |
| 44 Args: |
| 45 service_name: the service name. When this argument is unspecified, this |
| 46 method uses the value of the "SERVICE_NAME" environment variable as the |
| 47 service name, and raises ValueError if the environment variable is unset. |
| 48 service_version: the service version. When this argument is unspecified, |
| 49 this method uses the value of the "SERVICE_VERSION" environment variable |
| 50 as the service version, and raises ValueError if the environment variable |
| 51 is unset. |
| 52 |
| 53 Returns: the fetched service config JSON object. |
| 54 |
| 55 Raises: |
| 56 ValueError: when the service name/version is neither provided as an |
| 57 argument or set as an environment variable; or when the fetched service |
| 58 config fails validation. |
| 59 Exception: when the Google Service Management API returns non-200 response. |
| 60 """ |
| 61 if not service_name: |
| 62 service_name = _get_env_var_or_raise(_SERVICE_NAME_ENV_KEY) |
| 63 if not service_version: |
| 64 service_version = _get_env_var_or_raise(_SERVICE_VERSION_ENV_KEY) |
| 65 |
| 66 service_mgmt_url = _SERVICE_MGMT_URL_TEMPLATE.format(service_name, |
| 67 service_version) |
| 68 |
| 69 access_token = _get_access_token() |
| 70 headers = {"Authorization": "Bearer {}".format(access_token)} |
| 71 |
| 72 http_client = _get_http_client() |
| 73 response = http_client.request("GET", service_mgmt_url, headers=headers) |
| 74 |
| 75 status_code = response.status |
| 76 if status_code != 200: |
| 77 message_template = "Fetching service config failed (status code {})" |
| 78 _log_and_raise(Exception, message_template.format(status_code)) |
| 79 |
| 80 logger.debug('obtained service json from the management api:\n%s', response.da
ta) |
| 81 service = encoding.JsonToMessage(messages.Service, response.data) |
| 82 _validate_service_config(service, service_name, service_version) |
| 83 return service |
| 84 |
| 85 |
| 86 def _get_access_token(): |
| 87 credentials = client.GoogleCredentials.get_application_default() |
| 88 if credentials.create_scoped_required(): |
| 89 credentials = credentials.create_scoped(_GOOGLE_API_SCOPE) |
| 90 return credentials.get_access_token().access_token |
| 91 |
| 92 |
| 93 def _get_http_client(): |
| 94 if appengine.is_appengine_sandbox(): |
| 95 return appengine.AppEngineManager() |
| 96 else: |
| 97 return urllib3.PoolManager() |
| 98 |
| 99 |
| 100 def _get_env_var_or_raise(env_variable_name): |
| 101 if env_variable_name not in os.environ: |
| 102 message_template = 'The "{}" environment variable is not set' |
| 103 _log_and_raise(ValueError, message_template.format(env_variable_name)) |
| 104 return os.environ[env_variable_name] |
| 105 |
| 106 |
| 107 def _validate_service_config(service, expected_service_name, |
| 108 expected_service_version): |
| 109 service_name = service.name |
| 110 if not service_name: |
| 111 _log_and_raise(ValueError, "No service name in the service config") |
| 112 if service_name != expected_service_name: |
| 113 message_template = "Unexpected service name in service config: {}" |
| 114 _log_and_raise(ValueError, message_template.format(service_name)) |
| 115 |
| 116 service_version = service.id |
| 117 if not service_version: |
| 118 _log_and_raise(ValueError, "No service version in the service config") |
| 119 if service_version != expected_service_version: |
| 120 message_template = "Unexpected service version in service config: {}" |
| 121 _log_and_raise(ValueError, message_template.format(service_version)) |
| 122 |
| 123 |
| 124 def _log_and_raise(exception_class, message): |
| 125 logger.error(message) |
| 126 raise exception_class(message) |
OLD | NEW |