def test_path_given_does_not_exist(self):
    path = tempfile.mkdtemp()
    os.rmdir(path)

    self.assertEqual(
        path, api_server.get_storage_path(path, 'dev~example.com:myapp'))
    self.assertTrue(os.path.isdir(path))
Exemple #2
0
    def test_path_given_does_not_exist(self):
        path = tempfile.mkdtemp()
        os.rmdir(path)

        self.assertEqual(
            path, api_server.get_storage_path(path, 'dev~example.com:myapp'))
        self.assertTrue(os.path.isdir(path))
  def test_no_path_given_directory_does_not_exist(self):
    path = tempfile.mkdtemp()
    os.rmdir(path)
    api_server._generate_storage_paths('example.com_myapp').AndReturn([path])

    self.mox.ReplayAll()
    self.assertEqual(
        path, api_server.get_storage_path(None, 'dev~example.com:myapp'))
    self.mox.VerifyAll()
    self.assertTrue(os.path.isdir(path))
Exemple #4
0
    def test_no_path_given_directory_does_not_exist(self):
        path = tempfile.mkdtemp()
        os.rmdir(path)
        api_server._generate_storage_paths('example.com_myapp').AndReturn(
            [path])

        self.mox.ReplayAll()
        self.assertEqual(
            path, api_server.get_storage_path(None, 'dev~example.com:myapp'))
        self.mox.VerifyAll()
        self.assertTrue(os.path.isdir(path))
Exemple #5
0
    def test_no_path_given_directory_exists(self):
        path1 = tempfile.mkdtemp()
        os.chmod(path1, 0777)
        path2 = tempfile.mkdtemp()  # Made with mode 0700.

        api_server._generate_storage_paths('example.com_myapp').AndReturn(
            [path1, path2])

        self.mox.ReplayAll()
        if sys.platform == 'win32':
            expected_path = path1
        else:
            expected_path = path2
        self.assertEqual(
            expected_path,
            api_server.get_storage_path(None, 'dev~example.com:myapp'))
        self.mox.VerifyAll()
  def test_no_path_given_directory_exists(self):
    path1 = tempfile.mkdtemp()
    os.chmod(path1, 0777)
    path2 = tempfile.mkdtemp()  # Made with mode 0700.

    api_server._generate_storage_paths('example.com_myapp').AndReturn(
        [path1, path2])

    self.mox.ReplayAll()
    if sys.platform == 'win32':
      expected_path = path1
    else:
      expected_path = path2
    self.assertEqual(
        expected_path,
        api_server.get_storage_path(None, 'dev~example.com:myapp'))
    self.mox.VerifyAll()
Exemple #7
0
def setup_local():
    from google.appengine.tools.devappserver2.devappserver2 import PARSER
    options = PARSER.parse_args([APP_YAML_LOCAL_FILE, ])

    from google.appengine.tools.devappserver2.devappserver2 import application_configuration
    configuration = application_configuration.ApplicationConfiguration(options.config_paths, options.app_id)

    # set the app ID to make stubs happy, esp. datastore
    os.environ['APPLICATION_ID'] = configuration.app_id
    os.environ['AUTH_DOMAIN'] = 'localhost'
    os.environ['SERVER_NAME'] = 'localhost'
    os.environ['SERVER_PORT'] = '8080'

    try:
        from google.appengine.tools.devappserver2.api_server import get_storage_path
    except ImportError:
        from google.appengine.tools.devappserver2.devappserver2 import _get_storage_path as get_storage_path

    storage_path = get_storage_path(options.storage_path, configuration.app_id)
    setup_stubs(storage_path, options, configuration)
Exemple #8
0
    def test_path_given_exists(self):
        path = tempfile.mkdtemp()

        self.assertEqual(
            path, api_server.get_storage_path(path, 'dev~example.com:myapp'))
Exemple #9
0
    def start(self, options):
        """Start devappserver2 servers based on the provided command line arguments.

    Args:
      options: An argparse.Namespace containing the command line arguments.
    """
        logging.getLogger().setLevel(constants.LOG_LEVEL_TO_PYTHON_CONSTANT[
            options.dev_appserver_log_level])

        configuration = application_configuration.ApplicationConfiguration(
            options.config_paths, options.app_id)

        if options.skip_sdk_update_check:
            logging.info('Skipping SDK update check.')
        else:
            update_checker.check_for_updates(configuration)

        if options.port == 0:
            logging.warn(
                'DEFAULT_VERSION_HOSTNAME will not be set correctly with '
                '--port=0')

        _setup_environ(configuration.app_id,
                       configuration.modules[0].version_id)

        python_config = runtime_config_pb2.PythonConfig()
        if options.python_startup_script:
            python_config.startup_script = os.path.abspath(
                options.python_startup_script)
            if options.python_startup_args:
                python_config.startup_args = options.python_startup_args

        php_executable_path = (options.php_executable_path and os.path.abspath(
            options.php_executable_path))
        cloud_sql_config = runtime_config_pb2.CloudSQL()
        cloud_sql_config.mysql_host = options.mysql_host
        cloud_sql_config.mysql_port = options.mysql_port
        cloud_sql_config.mysql_user = options.mysql_user
        cloud_sql_config.mysql_password = options.mysql_password
        if options.mysql_socket:
            cloud_sql_config.mysql_socket = options.mysql_socket

        if options.max_module_instances is None:
            module_to_max_instances = {}
        elif isinstance(options.max_module_instances, int):
            module_to_max_instances = {
                module_configuration.module_name: options.max_module_instances
                for module_configuration in configuration.modules
            }
        else:
            module_to_max_instances = options.max_module_instances

        if options.threadsafe_override is None:
            module_to_threadsafe_override = {}
        elif isinstance(options.threadsafe_override, bool):
            module_to_threadsafe_override = {
                module_configuration.module_name: options.threadsafe_override
                for module_configuration in configuration.modules
            }
        else:
            module_to_threadsafe_override = options.threadsafe_override

        self._dispatcher = dispatcher.Dispatcher(
            configuration, options.host, options.port, options.auth_domain,
            constants.LOG_LEVEL_TO_RUNTIME_CONSTANT[options.log_level],
            php_executable_path, options.php_remote_debugging, python_config,
            cloud_sql_config, module_to_max_instances,
            options.use_mtime_file_watcher, options.automatic_restart,
            options.allow_skipped_files, module_to_threadsafe_override,
            options.external_api_port)

        request_data = wsgi_request_info.WSGIRequestInfo(self._dispatcher)
        storage_path = api_server.get_storage_path(options.storage_path,
                                                   configuration.app_id)

        apis = api_server.create_api_server(
            request_data, storage_path, options, configuration.app_id,
            configuration.modules[0].application_root)
        apis.start()
        self._running_modules.append(apis)

        self._dispatcher.start(apis.port, request_data)
        self._running_modules.append(self._dispatcher)

        xsrf_path = os.path.join(storage_path, 'xsrf')
        admin = admin_server.AdminServer(options.admin_host,
                                         options.admin_port, self._dispatcher,
                                         configuration, xsrf_path)
        admin.start()
        self._running_modules.append(admin)
    def start(self, options):
        """Start devappserver2 servers based on the provided command line arguments.

    Args:
      options: An argparse.Namespace containing the command line arguments.
    """
        self._options = options

        logging.getLogger().setLevel(constants.LOG_LEVEL_TO_PYTHON_CONSTANT[
            options.dev_appserver_log_level])

        parsed_env_variables = dict(options.env_variables or [])
        configuration = application_configuration.ApplicationConfiguration(
            config_paths=options.config_paths,
            app_id=options.app_id,
            runtime=options.runtime,
            env_variables=parsed_env_variables)

        if options.google_analytics_client_id:
            metrics_logger = metrics.GetMetricsLogger()
            metrics_logger.Start(
                options.google_analytics_client_id,
                options.google_analytics_user_agent,
                {module.runtime
                 for module in configuration.modules},
                {module.env or 'standard'
                 for module in configuration.modules})

        if options.skip_sdk_update_check:
            logging.info('Skipping SDK update check.')
        else:
            update_checker.check_for_updates(configuration)

        # There is no good way to set the default encoding from application code
        # (it needs to be done during interpreter initialization in site.py or
        # sitecustomize.py) so just warn developers if they have a different
        # encoding than production.
        if sys.getdefaultencoding() != constants.PROD_DEFAULT_ENCODING:
            logging.warning(
                'The default encoding of your local Python interpreter is set to %r '
                'while App Engine\'s production environment uses %r; as a result '
                'your code may behave differently when deployed.',
                sys.getdefaultencoding(), constants.PROD_DEFAULT_ENCODING)

        if options.port == 0:
            logging.warn(
                'DEFAULT_VERSION_HOSTNAME will not be set correctly with '
                '--port=0')

        _setup_environ(configuration.app_id)

        # grpc_proxy is only needed for python2 because remote_api_stub.py is
        # imported in local python runtime sandbox. For more details, see
        # grpc_proxy_util.py.
        grpc_proxy_port = portpicker.PickUnusedPort()
        self._dispatcher = dispatcher.Dispatcher(
            configuration, options.host, options.port, options.auth_domain,
            constants.LOG_LEVEL_TO_RUNTIME_CONSTANT[options.log_level],
            self._create_php_config(options),
            self._create_python_config(options, grpc_proxy_port),
            self._create_java_config(options), self._create_go_config(options),
            self._create_custom_config(options),
            self._create_cloud_sql_config(options),
            self._create_vm_config(options),
            self._create_module_to_setting(options.max_module_instances,
                                           configuration,
                                           '--max_module_instances'),
            options.use_mtime_file_watcher, options.watcher_ignore_re,
            options.automatic_restart, options.allow_skipped_files,
            self._create_module_to_setting(options.threadsafe_override,
                                           configuration,
                                           '--threadsafe_override'),
            options.external_port)

        wsgi_request_info_ = wsgi_request_info.WSGIRequestInfo(
            self._dispatcher)
        storage_path = api_server.get_storage_path(options.storage_path,
                                                   configuration.app_id)

        datastore_emulator_host = (
            parsed_env_variables['DATASTORE_EMULATOR_HOST']
            if 'DATASTORE_EMULATOR_HOST' in parsed_env_variables else None)

        apiserver = api_server.create_api_server(
            wsgi_request_info_, storage_path, options, configuration.app_id,
            configuration.modules[0].application_root, datastore_emulator_host)
        apiserver.start()
        self._running_modules.append(apiserver)

        if options.grpc_apis:
            grpc_apiserver = api_server.GRPCAPIServer(options.grpc_api_port)
            grpc_apiserver.start()
            self._running_modules.append(grpc_apiserver)

            # We declare grpc_proxy_util as global, otherwise it cannot be accessed
            # from outside of this function.
            global grpc_proxy_util
            # pylint: disable=g-import-not-at-top
            # We lazy import here because grpc binaries are not always present.
            from google.appengine.tools.devappserver2 import grpc_proxy_util
            grpc_proxy = grpc_proxy_util.GrpcProxyServer(grpc_proxy_port)
            grpc_proxy.start()
            self._running_modules.append(grpc_proxy)

        self._dispatcher.start(options.api_host, apiserver.port,
                               wsgi_request_info_, options.grpc_apis)

        xsrf_path = os.path.join(storage_path, 'xsrf')
        admin = admin_server.AdminServer(options.admin_host,
                                         options.admin_port, self._dispatcher,
                                         configuration, xsrf_path)
        admin.start()
        self._running_modules.append(admin)
        try:
            default = self._dispatcher.get_module_by_name('default')
            apiserver.set_balanced_address(default.balanced_address)
        except request_info.ModuleDoesNotExistError:
            logging.warning('No default module found. Ignoring.')
  def start(self, options):
    """Start devappserver2 servers based on the provided command line arguments.

    Args:
      options: An argparse.Namespace containing the command line arguments.
    """
    self._options = options

    logging.getLogger().setLevel(
        constants.LOG_LEVEL_TO_PYTHON_CONSTANT[options.dev_appserver_log_level])

    parsed_env_variables = dict(options.env_variables or [])
    configuration = application_configuration.ApplicationConfiguration(
        config_paths=options.config_paths,
        app_id=options.app_id,
        runtime=options.runtime,
        env_variables=parsed_env_variables)

    if options.google_analytics_client_id:
      metrics_logger = metrics.GetMetricsLogger()
      metrics_logger.Start(
          options.google_analytics_client_id,
          options.google_analytics_user_agent,
          {module.runtime for module in configuration.modules},
          {module.env or 'standard' for module in configuration.modules})

    if options.skip_sdk_update_check:
      logging.info('Skipping SDK update check.')
    else:
      update_checker.check_for_updates(configuration)

    # There is no good way to set the default encoding from application code
    # (it needs to be done during interpreter initialization in site.py or
    # sitecustomize.py) so just warn developers if they have a different
    # encoding than production.
    if sys.getdefaultencoding() != constants.PROD_DEFAULT_ENCODING:
      logging.warning(
          'The default encoding of your local Python interpreter is set to %r '
          'while App Engine\'s production environment uses %r; as a result '
          'your code may behave differently when deployed.',
          sys.getdefaultencoding(), constants.PROD_DEFAULT_ENCODING)

    if options.port == 0:
      logging.warn('DEFAULT_VERSION_HOSTNAME will not be set correctly with '
                   '--port=0')

    _setup_environ(configuration.app_id)

    # grpc_proxy is only needed for python2 because remote_api_stub.py is
    # imported in local python runtime sandbox. For more details, see
    # grpc_proxy_util.py.
    grpc_proxy_port = portpicker.PickUnusedPort()
    self._dispatcher = dispatcher.Dispatcher(
        configuration, options.host, options.port, options.auth_domain,
        constants.LOG_LEVEL_TO_RUNTIME_CONSTANT[options.log_level],





        self._create_php_config(options),
        self._create_python_config(options, grpc_proxy_port),
        self._create_java_config(options),
        self._create_go_config(options),
        self._create_custom_config(options),
        self._create_cloud_sql_config(options),
        self._create_vm_config(options),
        self._create_module_to_setting(options.max_module_instances,
                                       configuration, '--max_module_instances'),
        options.use_mtime_file_watcher, options.watcher_ignore_re,
        options.automatic_restart, options.allow_skipped_files,
        self._create_module_to_setting(
            options.threadsafe_override,
            configuration,
            '--threadsafe_override'),
        options.external_port)

    wsgi_request_info_ = wsgi_request_info.WSGIRequestInfo(self._dispatcher)
    storage_path = api_server.get_storage_path(
        options.storage_path, configuration.app_id)

    datastore_emulator_host = (
        parsed_env_variables['DATASTORE_EMULATOR_HOST']
        if 'DATASTORE_EMULATOR_HOST' in parsed_env_variables else None)

    apiserver = api_server.create_api_server(
        wsgi_request_info_, storage_path, options, configuration.app_id,
        configuration.modules[0].application_root, datastore_emulator_host)
    apiserver.start()
    self._running_modules.append(apiserver)

    if options.grpc_apis:
      grpc_apiserver = api_server.GRPCAPIServer(options.grpc_api_port)
      grpc_apiserver.start()
      self._running_modules.append(grpc_apiserver)

      # We declare grpc_proxy_util as global, otherwise it cannot be accessed
      # from outside of this function.
      global grpc_proxy_util
      # pylint: disable=g-import-not-at-top
      # We lazy import here because grpc binaries are not always present.
      from google.appengine.tools.devappserver2 import grpc_proxy_util
      grpc_proxy = grpc_proxy_util.GrpcProxyServer(grpc_proxy_port)
      grpc_proxy.start()
      self._running_modules.append(grpc_proxy)

    self._dispatcher.start(
        options.api_host, apiserver.port, wsgi_request_info_, options.grpc_apis)

    xsrf_path = os.path.join(storage_path, 'xsrf')
    admin = admin_server.AdminServer(options.admin_host, options.admin_port,
                                     self._dispatcher, configuration, xsrf_path)
    admin.start()
    self._running_modules.append(admin)
    try:
      default = self._dispatcher.get_module_by_name('default')
      apiserver.set_balanced_address(default.balanced_address)
    except request_info.ModuleDoesNotExistError:
      logging.warning('No default module found. Ignoring.')
Exemple #12
0
def _local(devappserver2=None, configuration=None, options=None, wsgi_request_info=None, **kwargs):

    # If we use `_LocalRequestInfo`, deferred tasks don't seem to work,
    # but with the default `WSGIRequestInfo`, building the request url for
    # blobstore uploads fails. So we inherit from `WSGIRequestInfo` and copy
    # the `get_request_url` from `_LocalRequestInfo`
    class CustomWSGIRequestInfo(wsgi_request_info.WSGIRequestInfo):
        def get_request_url(self, request_id):
            """Returns the URL the request e.g. 'http://localhost:8080/foo?bar=baz'.

            Args:
              request_id: The string id of the request making the API call.

            Returns:
              The URL of the request as a string.
            """
            try:
                host = os.environ['HTTP_HOST']
            except KeyError:
                host = os.environ['SERVER_NAME']
                port = os.environ['SERVER_PORT']
                if port != '80':
                    host += ':' + port
            url = 'http://' + host
            url += quote(os.environ.get('PATH_INFO', '/'))
            if os.environ.get('QUERY_STRING'):
                url += '?' + os.environ['QUERY_STRING']
            return url

    global _API_SERVER

    _disable_sqlite_stub_logging()

    original_environ = os.environ.copy()

    # Silence warnings about this being unset, localhost:8080 is the dev_appserver default.
    # Note that we're setting things for the *Blobstore* handler in os.environ here, which seems
    # kind of crazy, and probably is, but it seems to be necessary to make stuff work.
    url = "localhost"
    port = get_next_available_port(url, DEFAULT_BLOBSTORE_SERVICE_PORT)
    os.environ.setdefault("HTTP_HOST", "{}:{}".format(url, port))
    os.environ['SERVER_NAME'] = url
    os.environ['SERVER_PORT'] = str(port)
    os.environ['DEFAULT_VERSION_HOSTNAME'] = '%s:%s' % (os.environ['SERVER_NAME'], os.environ['SERVER_PORT'])

    devappserver2._setup_environ(configuration.app_id)

    from google.appengine.tools.devappserver2 import api_server
    from google.appengine.tools.sdk_update_checker import GetVersionObject, _VersionList

    if hasattr(api_server, "get_storage_path"):
        storage_path = api_server.get_storage_path(options.storage_path, configuration.app_id)
    else:
        # SDK < 1.9.51
        storage_path = devappserver2._get_storage_path(options.storage_path, configuration.app_id)

    dispatcher = _create_dispatcher(configuration, options)
    request_data = CustomWSGIRequestInfo(dispatcher)
    # Remember the wsgi request info object so it can be reused to avoid duplication.
    dispatcher._request_data = request_data

    # We set the API and Admin ports so that they are beyond any modules (if you
    # have 10 modules then these values will shift, but it's better that they are predictable
    # in the common case)
    options.api_port = get_next_available_port(url, max(DEFAULT_API_PORT, port + 1))
    options.admin_port = get_next_available_port(url, max(DEFAULT_ADMIN_PORT, options.api_port + 1))

    if hasattr(api_server, "create_api_server"):
        current_version = _VersionList(GetVersionObject()['release'])
        app_rather_than_config = current_version >= _VersionList('1.9.54')

        # Google changed the argument structure in version 1.9.54 so we have to
        # conditionally supply the args here
        if app_rather_than_config:
            _API_SERVER = api_server.create_api_server(
                request_data,
                storage_path,
                options,
                configuration.app_id,
                environment.get_application_root()
            )
        else:
            _API_SERVER = api_server.create_api_server(
                request_data, storage_path, options, configuration
            )

        # We have to patch api_server.create_api_server to return _API_SERVER
        # every time it's called, without this we end up with all kinds of
        # problems. Basically we need one api server for the lifetime of the
        # sandbox (including in `runserver`)
        def create_api_server_patch(*args, **kwargs):
            return _API_SERVER

        api_server.create_api_server = create_api_server_patch

    else:

        _API_SERVER = devappserver2.DevelopmentServer._create_api_server(
            request_data, storage_path, options, configuration
        )

    from .blobstore_service import start_blobstore_service, stop_blobstore_service

    start_blobstore_service()
    try:
        yield
    finally:
        api_server.cleanup_stubs()
        os.environ = original_environ
        stop_blobstore_service()
Exemple #13
0
  def start(self, options):
    """Start devappserver2 servers based on the provided command line arguments.

    Args:
      options: An argparse.Namespace containing the command line arguments.
    """
    logging.getLogger().setLevel(
        constants.LOG_LEVEL_TO_PYTHON_CONSTANT[options.dev_appserver_log_level])

    configuration = application_configuration.ApplicationConfiguration(
        options.config_paths, options.app_id)

    if options.skip_sdk_update_check:
      logging.info('Skipping SDK update check.')
    else:
      update_checker.check_for_updates(configuration)

    if options.port == 0:
      logging.warn('DEFAULT_VERSION_HOSTNAME will not be set correctly with '
                   '--port=0')

    _setup_environ(configuration.app_id, configuration.modules[0].version_id)

    python_config = runtime_config_pb2.PythonConfig()
    if options.python_startup_script:
      python_config.startup_script = os.path.abspath(
          options.python_startup_script)
      if options.python_startup_args:
        python_config.startup_args = options.python_startup_args

    php_executable_path = (options.php_executable_path and
                           os.path.abspath(options.php_executable_path))
    cloud_sql_config = runtime_config_pb2.CloudSQL()
    cloud_sql_config.mysql_host = options.mysql_host
    cloud_sql_config.mysql_port = options.mysql_port
    cloud_sql_config.mysql_user = options.mysql_user
    cloud_sql_config.mysql_password = options.mysql_password
    if options.mysql_socket:
      cloud_sql_config.mysql_socket = options.mysql_socket

    if options.max_module_instances is None:
      module_to_max_instances = {}
    elif isinstance(options.max_module_instances, int):
      module_to_max_instances = {
          module_configuration.module_name: options.max_module_instances
          for module_configuration in configuration.modules}
    else:
      module_to_max_instances = options.max_module_instances

    if options.threadsafe_override is None:
      module_to_threadsafe_override = {}
    elif isinstance(options.threadsafe_override, bool):
      module_to_threadsafe_override = {
          module_configuration.module_name: options.threadsafe_override
          for module_configuration in configuration.modules}
    else:
      module_to_threadsafe_override = options.threadsafe_override

    self._dispatcher = dispatcher.Dispatcher(
        configuration,
        options.host,
        options.port,
        options.auth_domain,
        constants.LOG_LEVEL_TO_RUNTIME_CONSTANT[options.log_level],
        php_executable_path,
        options.php_remote_debugging,
        python_config,
        cloud_sql_config,
        module_to_max_instances,
        options.use_mtime_file_watcher,
        options.automatic_restart,
        options.allow_skipped_files,
        module_to_threadsafe_override)

    request_data = wsgi_request_info.WSGIRequestInfo(self._dispatcher)
    storage_path = api_server.get_storage_path(
        options.storage_path, configuration.app_id)

    apis = api_server.create_api_server(
        request_data, storage_path, options, configuration.app_id,
        configuration.modules[0].application_root)
    apis.start()
    self._running_modules.append(apis)

    self._dispatcher.start(apis.port, request_data)
    self._running_modules.append(self._dispatcher)
Exemple #14
0
  def start(self, options):
    """Start devappserver2 servers based on the provided command line arguments.

    Args:
      options: An argparse.Namespace containing the command line arguments.

    Raises:
      PhpPathError: php executable path is not specified for php72.
      MissingDatastoreEmulatorError: dev_appserver.py is not invoked from the right
        directory.
    """
    self._options = options

    self._correct_datastore_emulator_cmd()
    self._fail_for_using_datastore_emulator_from_legacy_sdk()
    self._decide_use_datastore_emulator()

    logging.getLogger().setLevel(
        constants.LOG_LEVEL_TO_PYTHON_CONSTANT[options.dev_appserver_log_level])

    parsed_env_variables = dict(options.env_variables or [])

    if options.dev_appserver_log_setup_script:
      try:
        execfile(options.dev_appserver_log_setup_script, {}, {})
      except Exception as e:
        logging.exception("Error executing log setup script at %r.",
                          options.dev_appserver_log_setup_script)

    configuration = application_configuration.ApplicationConfiguration(
        config_paths=options.config_paths,
        app_id=options.app_id,
        runtime=options.runtime,
        env_variables=parsed_env_variables)
    all_module_runtimes = {module.runtime for module in configuration.modules}
    self._check_platform_support(all_module_runtimes)

    storage_path = api_server.get_storage_path(
        options.storage_path, configuration.app_id)
    datastore_path = api_server.get_datastore_path(
        storage_path, options.datastore_path)
    datastore_data_type = (datastore_converter.get_stub_type(datastore_path)
                           if os.path.isfile(datastore_path) else None)

    if options.skip_sdk_update_check:
      logging.info('Skipping SDK update check.')
    else:
      update_checker.check_for_updates(configuration)

    # There is no good way to set the default encoding from application code
    # (it needs to be done during interpreter initialization in site.py or
    # sitecustomize.py) so just warn developers if they have a different
    # encoding than production.
    if sys.getdefaultencoding() != constants.PROD_DEFAULT_ENCODING:
      logging.warning(
          'The default encoding of your local Python interpreter is set to %r '
          'while App Engine\'s production environment uses %r; as a result '
          'your code may behave differently when deployed.',
          sys.getdefaultencoding(), constants.PROD_DEFAULT_ENCODING)

    if options.port == 0:
      logging.warn('DEFAULT_VERSION_HOSTNAME will not be set correctly with '
                   '--port=0')

    util.setup_environ(configuration.app_id)

    php_version = self._get_php_runtime(configuration)
    if not options.php_executable_path and php_version == 'php72':
      raise PhpPathError('For php72, --php_executable_path must be specified.')

    if options.ssl_certificate_path and options.ssl_certificate_key_path:
      ssl_certificate_paths = self._create_ssl_certificate_paths_if_valid(
          options.ssl_certificate_path, options.ssl_certificate_key_path)
    else:
      if options.ssl_certificate_path or options.ssl_certificate_key_path:
        logging.warn('Must provide both --ssl_certificate_path and '
                     '--ssl_certificate_key_path to enable SSL. Since '
                     'only one flag was provided, not using SSL.')
      ssl_certificate_paths = None

    if options.google_analytics_client_id:
      metrics_logger = metrics.GetMetricsLogger()
      metrics_logger.Start(
          options.google_analytics_client_id,
          options.google_analytics_user_agent,
          all_module_runtimes,
          {module.env or 'standard' for module in configuration.modules},
          options.support_datastore_emulator, datastore_data_type,
          bool(ssl_certificate_paths), options,
          multi_module=len(configuration.modules) > 1,
          dispatch_config=configuration.dispatch is not None,
          grpc_import_report=self.grpc_import_report,
          java_major_version=self.java_major_version
      )

    self._dispatcher = dispatcher.Dispatcher(
        configuration, options.host, options.port, options.auth_domain,
        constants.LOG_LEVEL_TO_RUNTIME_CONSTANT[options.log_level],
        self._create_php_config(options, php_version),
        self._create_python_config(options),
        self._create_java_config(options),
        self._create_go_config(options),
        self._create_custom_config(options),
        self._create_cloud_sql_config(options),
        self._create_vm_config(options),
        self._create_module_to_setting(options.max_module_instances,
                                       configuration, '--max_module_instances'),
        options.use_mtime_file_watcher, options.watcher_ignore_re,
        options.automatic_restart, options.allow_skipped_files,
        self._create_module_to_setting(
            options.threadsafe_override,
            configuration,
            '--threadsafe_override'),
        options.external_port,
        options.specified_service_ports,
        options.enable_host_checking,
        ssl_certificate_paths)

    wsgi_request_info_ = wsgi_request_info.WSGIRequestInfo(self._dispatcher)

    apiserver = api_server.create_api_server(
        wsgi_request_info_, storage_path, options, configuration.app_id,
        configuration.modules[0].application_root)
    apiserver.start()
    self._running_modules.append(apiserver)

    self._dispatcher.start(
        options.api_host, apiserver.port, wsgi_request_info_)

    xsrf_path = os.path.join(storage_path, 'xsrf')
    admin = admin_server.AdminServer(options.admin_host, options.admin_port,
                                     self._dispatcher, configuration, xsrf_path,
                                     options.enable_host_checking,
                                     options.enable_console)
    admin.start()
    self._running_modules.append(admin)

    if options.enable_datastore_translator:
      # We do a late import just in case of any problems with importing
      # protobuf (although in theory python/wrapper_util.py's path-munging has
      # handled them all).
      from google.appengine.tools.devappserver2.datastore_translator import (
        datastore_translator_server)
      translator = datastore_translator_server.DatastoreTranslatorServer(
        options.datastore_translator_host, options.datastore_translator_port,
        options.enable_host_checking)
      translator.start()
      self._running_modules.append(translator)

    try:
      default = self._dispatcher.get_module_by_name('default')
      apiserver.set_balanced_address(default.balanced_address)
    except request_info.ModuleDoesNotExistError:
      logging.warning('No default module found. Ignoring.')
Exemple #15
0
  def test_path_given_exists(self):
    path = tempfile.mkdtemp()

    self.assertEqual(
        path, api_server.get_storage_path(path, 'dev~example.com:myapp'))
Exemple #16
0
    def start(self, options):
        """Start devappserver2 servers based on the provided command line arguments.

    Args:
      options: An argparse.Namespace containing the command line arguments.
    """
        self._options = options

        logging.getLogger().setLevel(constants.LOG_LEVEL_TO_PYTHON_CONSTANT[
            options.dev_appserver_log_level])

        parsed_env_variables = dict(options.env_variables or [])
        configuration = application_configuration.ApplicationConfiguration(
            config_paths=options.config_paths,
            app_id=options.app_id,
            runtime=options.runtime,
            env_variables=parsed_env_variables)

        if options.google_analytics_client_id:
            metrics_logger = metrics.GetMetricsLogger()
            metrics_logger.Start(
                options.google_analytics_client_id,
                options.google_analytics_user_agent,
                {module.runtime
                 for module in configuration.modules},
                {module.env or 'standard'
                 for module in configuration.modules})

        if options.skip_sdk_update_check:
            logging.info('Skipping SDK update check.')
        else:
            update_checker.check_for_updates(configuration)

        # There is no good way to set the default encoding from application code
        # (it needs to be done during interpreter initialization in site.py or
        # sitecustomize.py) so just warn developers if they have a different
        # encoding than production.
        if sys.getdefaultencoding() != constants.PROD_DEFAULT_ENCODING:
            logging.warning(
                'The default encoding of your local Python interpreter is set to %r '
                'while App Engine\'s production environment uses %r; as a result '
                'your code may behave differently when deployed.',
                sys.getdefaultencoding(), constants.PROD_DEFAULT_ENCODING)

        if options.port == 0:
            logging.warn(
                'DEFAULT_VERSION_HOSTNAME will not be set correctly with '
                '--port=0')

        _setup_environ(configuration.app_id)

        self._dispatcher = dispatcher.Dispatcher(
            configuration, options.host, options.port, options.auth_domain,
            constants.LOG_LEVEL_TO_RUNTIME_CONSTANT[options.log_level],
            self._create_php_config(options),
            self._create_python_config(options),
            self._create_java_config(options), self._create_go_config(options),
            self._create_custom_config(options),
            self._create_cloud_sql_config(options),
            self._create_vm_config(options),
            self._create_module_to_setting(options.max_module_instances,
                                           configuration,
                                           '--max_module_instances'),
            options.use_mtime_file_watcher, options.watcher_ignore_re,
            options.automatic_restart, options.allow_skipped_files,
            self._create_module_to_setting(options.threadsafe_override,
                                           configuration,
                                           '--threadsafe_override'),
            options.external_port)

        wsgi_request_info_ = wsgi_request_info.WSGIRequestInfo(
            self._dispatcher)
        storage_path = api_server.get_storage_path(options.storage_path,
                                                   configuration.app_id)

        apiserver = api_server.create_api_server(
            wsgi_request_info_, storage_path, options, configuration.app_id,
            configuration.modules[0].application_root)
        apiserver.start()
        self._running_modules.append(apiserver)

        self._dispatcher.start(options.api_host, apiserver.port,
                               wsgi_request_info_)

        xsrf_path = os.path.join(storage_path, 'xsrf')
        admin = admin_server.AdminServer(options.admin_host,
                                         options.admin_port, self._dispatcher,
                                         configuration, xsrf_path)
        admin.start()
        self._running_modules.append(admin)
        try:
            default = self._dispatcher.get_module_by_name('default')
            apiserver.set_balanced_address(default.balanced_address)
        except request_info.ModuleDoesNotExistError:
            logging.warning('No default module found. Ignoring.')
Exemple #17
0
def _local(devappserver2=None, configuration=None, options=None, wsgi_request_info=None, **kwargs):

    # If we use `_LocalRequestInfo`, deferred tasks don't seem to work,
    # but with the default `WSGIRequestInfo`, building the request url for
    # blobstore uploads fails. So we inherit from `WSGIRequestInfo` and copy
    # the `get_request_url` from `_LocalRequestInfo`
    class CustomWSGIRequestInfo(wsgi_request_info.WSGIRequestInfo):
        def get_request_url(self, request_id):
            """Returns the URL the request e.g. 'http://localhost:8080/foo?bar=baz'.

            Args:
              request_id: The string id of the request making the API call.

            Returns:
              The URL of the request as a string.
            """
            try:
                host = os.environ['HTTP_HOST']
            except KeyError:
                host = os.environ['SERVER_NAME']
                port = os.environ['SERVER_PORT']
                if port != '80':
                    host += ':' + port
            url = 'http://' + host
            url += urllib.quote(os.environ.get('PATH_INFO', '/'))
            if os.environ.get('QUERY_STRING'):
                url += '?' + os.environ['QUERY_STRING']
            return url

    global _API_SERVER

    _disable_sqlite_stub_logging()

    original_environ = os.environ.copy()

    # Silence warnings about this being unset, localhost:8080 is the dev_appserver default.
    # Note that we're setting things for the *Blobstore* handler in os.environ here, which seems
    # kind of crazy, and probably is, but it seems to be necessary to make stuff work.
    url = "localhost"
    port = get_next_available_port(url, DEFAULT_BLOBSTORE_SERVICE_PORT)
    os.environ.setdefault("HTTP_HOST", "{}:{}".format(url, port))
    os.environ['SERVER_NAME'] = url
    os.environ['SERVER_PORT'] = str(port)
    os.environ['DEFAULT_VERSION_HOSTNAME'] = '%s:%s' % (os.environ['SERVER_NAME'], os.environ['SERVER_PORT'])

    devappserver2._setup_environ(configuration.app_id)

    from google.appengine.tools.devappserver2 import api_server
    if hasattr(api_server, "get_storage_path"):
        storage_path = api_server.get_storage_path(options.storage_path, configuration.app_id)
    else:
        # SDK < 1.9.51
        storage_path = devappserver2._get_storage_path(options.storage_path, configuration.app_id)

    dispatcher = _create_dispatcher(configuration, options)
    request_data = CustomWSGIRequestInfo(dispatcher)
    # Remember the wsgi request info object so it can be reused to avoid duplication.
    dispatcher._request_data = request_data

    # We set the API and Admin ports so that they are beyond any modules (if you
    # have 10 modules then these values will shift, but it's better that they are predictable
    # in the common case)
    options.api_port = get_next_available_port(url, DEFAULT_API_PORT)
    options.admin_port = get_next_available_port(url, DEFAULT_ADMIN_PORT)

    if hasattr(api_server, "create_api_server"):
        _API_SERVER = api_server.create_api_server(
            request_data, storage_path, options, configuration
        )

        # We have to patch api_server.create_api_server to return _API_SERVER
        # every time it's called, without this we end up with all kinds of
        # problems. Basically we need one api server for the lifetime of the
        # sandbox (including in `runserver`)
        def create_api_server_patch(*args, **kwargs):
            return _API_SERVER

        api_server.create_api_server = create_api_server_patch

    else:
        _API_SERVER = devappserver2.DevelopmentServer._create_api_server(
            request_data, storage_path, options, configuration
        )

    from .blobstore_service import start_blobstore_service, stop_blobstore_service

    start_blobstore_service()
    try:
        yield
    finally:
        api_server.cleanup_stubs()
        os.environ = original_environ
        stop_blobstore_service()
Exemple #18
0
    def start(self, options):
        """Start devappserver2 servers based on the provided command line arguments.

    Args:
      options: An argparse.Namespace containing the command line arguments.

    Raises:
      PhpPathError: php executable path is not specified for php72.
      MissingDatastoreEmulatorError: dev_appserver.py is not invoked from the right
        directory.
    """
        self._options = options

        self._options.datastore_emulator_cmd = self._correct_datastore_emulator_cmd(
            self._options.datastore_emulator_cmd)
        self._check_datastore_emulator_support()

        logging.getLogger().setLevel(constants.LOG_LEVEL_TO_PYTHON_CONSTANT[
            options.dev_appserver_log_level])

        parsed_env_variables = dict(options.env_variables or [])
        configuration = application_configuration.ApplicationConfiguration(
            config_paths=options.config_paths,
            app_id=options.app_id,
            runtime=options.runtime,
            env_variables=parsed_env_variables)
        all_module_runtimes = {
            module.runtime
            for module in configuration.modules
        }
        self._check_platform_support(all_module_runtimes)

        storage_path = api_server.get_storage_path(options.storage_path,
                                                   configuration.app_id)
        datastore_path = api_server.get_datastore_path(storage_path,
                                                       options.datastore_path)
        datastore_data_type = (
            datastore_converter.get_stub_type(datastore_path)
            if os.path.isfile(datastore_path) else None)

        if options.skip_sdk_update_check:
            logging.info('Skipping SDK update check.')
        else:
            update_checker.check_for_updates(configuration)

        # There is no good way to set the default encoding from application code
        # (it needs to be done during interpreter initialization in site.py or
        # sitecustomize.py) so just warn developers if they have a different
        # encoding than production.
        if sys.getdefaultencoding() != constants.PROD_DEFAULT_ENCODING:
            logging.warning(
                'The default encoding of your local Python interpreter is set to %r '
                'while App Engine\'s production environment uses %r; as a result '
                'your code may behave differently when deployed.',
                sys.getdefaultencoding(), constants.PROD_DEFAULT_ENCODING)

        if options.port == 0:
            logging.warn(
                'DEFAULT_VERSION_HOSTNAME will not be set correctly with '
                '--port=0')

        util.setup_environ(configuration.app_id)

        php_version = self._get_php_runtime(configuration)
        if not options.php_executable_path and php_version == 'php72':
            raise PhpPathError(
                'For php72, --php_executable_path must be specified.')

        if options.ssl_certificate_path and options.ssl_certificate_key_path:
            ssl_certificate_paths = self._create_ssl_certificate_paths_if_valid(
                options.ssl_certificate_path, options.ssl_certificate_key_path)
        else:
            if options.ssl_certificate_path or options.ssl_certificate_key_path:
                logging.warn('Must provide both --ssl_certificate_path and '
                             '--ssl_certificate_key_path to enable SSL. Since '
                             'only one flag was provided, not using SSL.')
            ssl_certificate_paths = None

        if options.google_analytics_client_id:
            metrics_logger = metrics.GetMetricsLogger()
            metrics_logger.Start(
                options.google_analytics_client_id,
                options.google_analytics_user_agent,
                all_module_runtimes,
                {module.env or 'standard'
                 for module in configuration.modules},
                options.support_datastore_emulator,
                datastore_data_type,
                bool(ssl_certificate_paths),
                options,
                multi_module=len(configuration.modules) > 1,
                dispatch_config=configuration.dispatch is not None,
            )

        self._dispatcher = dispatcher.Dispatcher(
            configuration, options.host, options.port, options.auth_domain,
            constants.LOG_LEVEL_TO_RUNTIME_CONSTANT[options.log_level],
            self._create_php_config(options, php_version),
            self._create_python_config(options),
            self._create_java_config(options), self._create_go_config(options),
            self._create_custom_config(options),
            self._create_cloud_sql_config(options),
            self._create_vm_config(options),
            self._create_module_to_setting(options.max_module_instances,
                                           configuration,
                                           '--max_module_instances'),
            options.use_mtime_file_watcher, options.watcher_ignore_re,
            options.automatic_restart, options.allow_skipped_files,
            self._create_module_to_setting(options.threadsafe_override,
                                           configuration,
                                           '--threadsafe_override'),
            options.external_port, options.specified_service_ports,
            options.enable_host_checking, ssl_certificate_paths)

        wsgi_request_info_ = wsgi_request_info.WSGIRequestInfo(
            self._dispatcher)

        apiserver = api_server.create_api_server(
            wsgi_request_info_, storage_path, options, configuration.app_id,
            configuration.modules[0].application_root)
        apiserver.start()
        self._running_modules.append(apiserver)

        self._dispatcher.start(options.api_host, apiserver.port,
                               wsgi_request_info_)

        xsrf_path = os.path.join(storage_path, 'xsrf')
        admin = admin_server.AdminServer(options.admin_host,
                                         options.admin_port, self._dispatcher,
                                         configuration, xsrf_path,
                                         options.enable_host_checking,
                                         options.enable_console)
        admin.start()
        self._running_modules.append(admin)
        try:
            default = self._dispatcher.get_module_by_name('default')
            apiserver.set_balanced_address(default.balanced_address)
        except request_info.ModuleDoesNotExistError:
            logging.warning('No default module found. Ignoring.')