docker/serverless/env_start_proxy.py (93 lines of code) (raw):

#!/usr/bin/env python # # Copyright 2019 Google LLC # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License 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 os import logging MISSING_SERVICE_CONFIG_ERROR = ''' Did you forget to build the Endpoints service configuration into the ESPv2 image? Please refer to the official serverless quickstart tutorials (below) for more information. https://cloud.google.com/endpoints/docs/openapi/get-started-cloud-run#configure_esp https://cloud.google.com/endpoints/docs/openapi/get-started-cloud-functions#configure_esp https://cloud.google.com/endpoints/docs/grpc/get-started-cloud-run#configure_esp If you are following along with these tutorials but have not reached the step above yet, this error is expected. Feel free to temporarily disregard this error message. If you wish to skip this step, please specify the name of the service in the ENDPOINTS_SERVICE_NAME environment variable. Note this deployment mode is **not** officially supported. It is recommended that you follow the tutorials linked above. ''' MALFORMED_ESPv2_ARGS_ERROR = ''' Malformed ESPv2_ARGS environment variable. Please refer to the official ESPv2 startup reference (below) for information on how to format ESPv2_ARGS. https://cloud.google.com/endpoints/docs/openapi/specify-esp-v2-startup-options#setting-configuration-flags ''' def assert_env_var(name, help_msg=""): if name not in os.environ: raise AssertionError( "Serverless ESPv2 expects {} in environment variables.\n{}" .format(name, help_msg) ) def make_error_app(msg): # error_msg must be a utf-8 or ascii bytestring def error_app(environ, start_response): start_response("503 Service Unavailable", [("Content-Type", "text/plain")]) return [msg.encode("utf-8")] return error_app def serve_msg(msg): import wsgiref.simple_server app = make_error_app(msg) port = int(os.environ["PORT"]) server = wsgiref.simple_server.make_server("", port, app) server.serve_forever() def serve_error_msg(msg): logging.error(msg) serve_msg(msg) def serve_warning_msg(msg): logging.warning(msg) serve_msg(msg) def gen_args(cmd): ARGS = [ cmd, "/apiproxy/start_proxy.py", "--on_serverless" ] # Uncaught AssertionError; # if no port, we can't serve a nice error handler. Crash instead. assert_env_var("PORT") ARGS.append("--http_port={}".format(os.environ["PORT"])) if "ENDPOINTS_SERVICE_PATH" in os.environ: ARGS.extend( [ "--rollout_strategy=fixed", "--service_json_path={}".format(os.environ["ENDPOINTS_SERVICE_PATH"]), ] ) else: try: assert_env_var( "ENDPOINTS_SERVICE_NAME", MISSING_SERVICE_CONFIG_ERROR ) except AssertionError as error: serve_warning_msg(str(error)) ARGS.append("--service={}".format(os.environ["ENDPOINTS_SERVICE_NAME"])) if "ENDPOINTS_SERVICE_VERSION" in os.environ: ARGS.extend( [ "--rollout_strategy=fixed", "--version={}".format(os.environ["ENDPOINTS_SERVICE_VERSION"]), ] ) else: ARGS.append("--rollout_strategy=managed") if "ESPv2_ARGS" in os.environ: # By default, ESPv2_ARGS is comma-separated. # But if a comma needs to appear within an arg, there is an alternative # syntax: Pick a replacement delimiter, specify it at the beginning of the # string between two caret (^) symbols, and use it within the arg string. # Example: # ^++^--cors_allow_methods="GET,POST,PUT,OPTIONS"++--cors_allow_credentials arg_value = os.environ["ESPv2_ARGS"] delim = "," if arg_value.startswith("^") and "^" in arg_value[1:]: delim, arg_value = arg_value[1:].split("^", 1) if not delim: serve_error_msg(MALFORMED_ESPv2_ARGS_ERROR) ARGS.extend(arg_value.split(delim)) return ARGS if __name__ == "__main__": logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.INFO) cmd = "/usr/bin/python3" args = gen_args(cmd) os.execv(cmd, args)