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)