def __init__(self, config_path, app_id=None, runtime=None, env_variables=None): """Initializer for ModuleConfiguration. Args: config_path: A string containing the full path of the yaml or xml file containing the configuration for this module. app_id: A string that is the application id, or None if the application id from the yaml or xml file should be used. runtime: A string that is the runtime to use, or None if the runtime from the yaml or xml file should be used. env_variables: A dictionary that is the environment variables passed by flags. Raises: errors.DockerfileError: Raised if a user supplied a Dockerfile and a non-custom runtime. errors.InvalidAppConfigError: Raised if a user select python vanilla runtime. """ self._config_path = config_path self._forced_app_id = app_id root = os.path.dirname(config_path) self._is_java = os.path.normpath(config_path).endswith( os.sep + 'WEB-INF' + os.sep + 'appengine-web.xml') if self._is_java: # We assume Java's XML-based config files only if config_path is # something like /foo/bar/WEB-INF/appengine-web.xml. In this case, # the application root is /foo/bar. Other apps, configured with YAML, # have something like /foo/bar/app.yaml, with application root /foo/bar. root = os.path.dirname(root) self._application_root = os.path.realpath(root) self._last_failure_message = None self._app_info_external, files_to_check = self._parse_configuration( self._config_path) # This if-statement is necessary because of following corner case # appinfo.EnvironmentVariables.Merge({}, None) returns None if env_variables: merged_env_variables = appinfo.EnvironmentVariables.Merge( self._app_info_external.env_variables, env_variables) self._app_info_external.env_variables = merged_env_variables self._mtimes = self._get_mtimes(files_to_check) self._application = '%s~%s' % (self.partition, self.application_external_name) self._api_version = self._app_info_external.api_version self._module_name = self._app_info_external.module self._version = self._app_info_external.version self._threadsafe = self._app_info_external.threadsafe self._basic_scaling_config = self._app_info_external.basic_scaling self._manual_scaling_config = self._app_info_external.manual_scaling self._automatic_scaling_config = self._app_info_external.automatic_scaling self._runtime = runtime or self._app_info_external.runtime self._effective_runtime = self._app_info_external.GetEffectiveRuntime() if self._runtime == 'python-compat': logging.warn( 'The python-compat runtime is deprecated, please consider upgrading ' 'your application to use the Flexible runtime. See ' 'https://cloud.google.com/appengine/docs/flexible/python/upgrading ' 'for more details.') elif self._runtime == 'vm': logging.warn( 'The Managed VMs runtime is deprecated, please consider migrating ' 'your application to use the Flexible runtime. See ' 'https://cloud.google.com/appengine/docs/flexible/python/migrating ' 'for more details.') dockerfile_dir = os.path.dirname(self._config_path) dockerfile = os.path.join(dockerfile_dir, 'Dockerfile') if self._effective_runtime != 'custom' and os.path.exists(dockerfile): raise errors.DockerfileError( 'When there is a Dockerfile in the current directory, the only ' 'supported runtime is runtime: custom. Please switch to runtime: ' 'custom. The devappserver does not actually use your Dockerfile, so ' 'please use either the --runtime flag to specify the runtime you ' 'want or use the --custom_entrypoint flag to describe how to start ' 'your application.') if self._runtime == 'python': logging.warning( 'The "python" runtime specified in "%s" is not supported - the ' '"python27" runtime will be used instead. A description of the ' 'differences between the two can be found here:\n' 'https://developers.google.com/appengine/docs/python/python25/diff27', self._config_path) self._minor_version_id = ''.join( random.choice(string.digits) for _ in range(18)) self._forwarded_ports = {} if self.runtime == 'vm': # Avoid using python-vanilla with dev_appserver if 'python' == self._effective_runtime: raise errors.InvalidAppConfigError( 'Under dev_appserver, ' 'runtime:python is not supported ' 'for Flexible environment.') # Java uses an api_version of 1.0 where everyone else uses just 1. # That doesn't matter much elsewhere, but it does pain us with VMs # because they recognize api_version 1 not 1.0. # TODO: sort out this situation better, probably by changing # Java to use 1 like everyone else. if self._api_version == '1.0': self._api_version = '1' vm_settings = self._app_info_external.vm_settings ports = None if vm_settings: ports = vm_settings.get('forwarded_ports') if not ports: if (self._app_info_external.network and self._app_info_external.network.forwarded_ports): # Depending on the YAML formatting, these may be strings or ints. # Force them to be strings. ports = ','.join( str(p) for p in self._app_info_external.network.forwarded_ports) if ports: logging.debug('setting forwarded ports %s', ports) pm = port_manager.PortManager() pm.Add(ports, 'forwarded') self._forwarded_ports = pm.GetAllMappedPorts()['tcp'] self._translate_configuration_files() # vm_health_check is deprecated but it still needs to be taken into account # if it is populated. if self._app_info_external.health_check is not None: health_check = self._app_info_external.health_check else: health_check = self._app_info_external.vm_health_check self._health_check = _set_health_check_defaults(health_check) # Configure the _is_{typeof}_scaling, _instance_class, and _memory_limit # attributes. self._is_manual_scaling = None self._is_basic_scaling = None self._is_automatic_scaling = None self._instance_class = self._app_info_external.instance_class if self._manual_scaling_config or self._runtime == 'vm': # TODO: Remove this 'or' when we support auto-scaled VMs. self._is_manual_scaling = True self._instance_class = ( self._instance_class or constants.DEFAULT_MANUAL_SCALING_INSTANCE_CLASS) elif self._basic_scaling_config: self._is_basic_scaling = True self._instance_class = ( self._instance_class or constants.DEFAULT_BASIC_SCALING_INSTANCE_CLASS) else: self._is_automatic_scaling = True self._instance_class = ( self._instance_class or constants.DEFAULT_AUTO_SCALING_INSTANCE_CLASS) self._memory_limit = constants.INSTANCE_CLASS_MEMORY_LIMIT.get( self._instance_class)
def __init__(self, config_path, app_id=None): """Initializer for ModuleConfiguration. Args: config_path: A string containing the full path of the yaml or xml file containing the configuration for this module. app_id: A string that is the application id, or None if the application id from the yaml or xml file should be used. Raises: errors.DockerfileError: Raised if a user supplied a Dockerfile and a non-custom runtime. """ self._config_path = config_path self._forced_app_id = app_id root = os.path.dirname(config_path) self._is_java = os.path.normpath(config_path).endswith( os.sep + 'WEB-INF' + os.sep + 'appengine-web.xml') if self._is_java: # We assume Java's XML-based config files only if config_path is # something like /foo/bar/WEB-INF/appengine-web.xml. In this case, # the application root is /foo/bar. Other apps, configured with YAML, # have something like /foo/bar/app.yaml, with application root /foo/bar. root = os.path.dirname(root) self._application_root = os.path.realpath(root) self._last_failure_message = None self._app_info_external, files_to_check = self._parse_configuration( self._config_path) # TODO: As in AppengineApiClient._CreateVersionResource, # add deprecation warnings and remove this code if self._app_info_external.service: self._app_info_external.module = self._app_info_external.service self._mtimes = self._get_mtimes(files_to_check) self._application = '%s~%s' % (self.partition, self.application_external_name) self._api_version = self._app_info_external.api_version self._module_name = self._app_info_external.module self._version = self._app_info_external.version self._threadsafe = self._app_info_external.threadsafe self._basic_scaling = self._app_info_external.basic_scaling self._manual_scaling = self._app_info_external.manual_scaling self._automatic_scaling = self._app_info_external.automatic_scaling self._runtime = self._app_info_external.runtime self._effective_runtime = self._app_info_external.GetEffectiveRuntime() dockerfile_dir = os.path.dirname(self._config_path) dockerfile = os.path.join(dockerfile_dir, 'Dockerfile') if self._effective_runtime != 'custom' and os.path.exists(dockerfile): raise errors.DockerfileError( 'When there is a Dockerfile in the current directory, the only ' 'supported runtime is runtime: custom. Please switch to runtime: ' 'custom. The devappserver does not actually use your Dockerfile, so ' 'please use either the --runtime flag to specify the runtime you ' 'want or use the --custom_entrypoint flag to describe how to start ' 'your application.') if self._runtime == 'python': logging.warning( 'The "python" runtime specified in "%s" is not supported - the ' '"python27" runtime will be used instead. A description of the ' 'differences between the two can be found here:\n' 'https://developers.google.com/appengine/docs/python/python25/diff27', self._config_path) self._minor_version_id = ''.join( random.choice(string.digits) for _ in range(18)) self._forwarded_ports = {} if self.runtime == 'vm': # Java uses an api_version of 1.0 where everyone else uses just 1. # That doesn't matter much elsewhere, but it does pain us with VMs # because they recognize api_version 1 not 1.0. # TODO: sort out this situation better, probably by changing # Java to use 1 like everyone else. if self._api_version == '1.0': self._api_version = '1' vm_settings = self._app_info_external.vm_settings ports = None if vm_settings: ports = vm_settings.get('forwarded_ports') if not ports: if (self._app_info_external.network and self._app_info_external.network.forwarded_ports): # Depending on the YAML formatting, these may be strings or ints. # Force them to be strings. ports = ','.join( str(p) for p in self._app_info_external.network.forwarded_ports) if ports: logging.debug('setting forwarded ports %s', ports) pm = port_manager.PortManager() pm.Add(ports, 'forwarded') self._forwarded_ports = pm.GetAllMappedPorts()['tcp'] self._translate_configuration_files() # vm_health_check is deprecated but it still needs to be taken into account # if it is populated. if self._app_info_external.health_check is not None: health_check = self._app_info_external.health_check else: health_check = self._app_info_external.vm_health_check self._health_check = _set_health_check_defaults(health_check)