def get_app_config()

in scripts/gen_dockerfile.py [0:0]


def get_app_config(raw_config, base_image, config_file, source_dir):
    """Read and validate the application runtime configuration.

    We validate the user input for security and better error messages.

    Consider parsing a yaml file which has a string value where we
    expected a list.  Python will happily use the string as a sequence
    of individual characters, at least for a while, leading to
    confusing results when it finally fails.

    We also try to prevent Dockerfile and Bash injection attacks.  For
    example, specifying entrypoint as "true\\nADD /etc/passwd /pwned"
    would allow the user to inject arbitrary directives into the
    Dockerfile, which is a support problem if nothing else.

    Args:
        raw_config (dict): deserialized app.yaml
        base_image (str): Docker image name to build on top of
        config_file (str): Path to user's app.yaml (might be <service>.yaml)
        source_dir (str): Directory containing user's source code

    Returns:
        AppConfig: valid configuration
    """
    # Examine app.yaml
    if not isinstance(raw_config, collections.abc.Mapping):
        raise ValueError(
            'Expected {} contents to be a Mapping type, but found type "{}"'.
            format(config_file, type(raw_config)))

    # Short circuit for python compat.
    if validation_utils.get_field_value(
        raw_config, 'runtime', str) == 'python-compat':
      return AppConfig(
          base_image=None,
          dockerfile_python_version=None,
          entrypoint=None,
          has_requirements_txt=None,
          is_python_compat=True)

    entrypoint = validation_utils.get_field_value(
        raw_config, 'entrypoint', str)
    if not PRINTABLE_REGEX.match(entrypoint):
        raise ValueError(
            'Invalid "entrypoint" value in app.yaml: {!r}'.format(entrypoint))

    # Mangle entrypoint in the same way as the Cloud SDK
    # (googlecloudsdk/third_party/appengine/api/validation.py)
    #
    # We could handle both string ("shell form") and list ("exec
    # form") but it appears that gcloud only handles string form.
    if entrypoint and not entrypoint.startswith('exec '):
        entrypoint = 'exec ' + entrypoint

    raw_runtime_config = validation_utils.get_field_value(
        raw_config, 'runtime_config', dict)
    python_version = validation_utils.get_field_value(
        raw_runtime_config, 'python_version', str)

    dockerfile_python_version = PYTHON_INTERPRETER_VERSION_MAP.get(
        python_version)
    if dockerfile_python_version is None:
        valid_versions = str(sorted(PYTHON_INTERPRETER_VERSION_MAP.keys()))
        raise ValueError(
            'Invalid "python_version" field in "runtime_config" section '
            'of app.yaml: {!r}.  Valid options are: {}'.
            format(python_version, valid_versions))

    # Examine user's files
    has_requirements_txt = os.path.isfile(
        os.path.join(source_dir, 'requirements.txt'))

    return AppConfig(
        base_image=base_image,
        dockerfile_python_version=dockerfile_python_version,
        entrypoint=entrypoint,
        has_requirements_txt=has_requirements_txt,
        is_python_compat=False)