Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions lib/galaxy/managers/_config_templates.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

from galaxy.exceptions import (
InconsistentDatabase,
InternalServerError,
ObjectNotFound,
RequestParameterInvalidException,
RequestParameterMissingException,
Expand Down Expand Up @@ -277,13 +278,19 @@ def prepare_environment_from_root(
secret_value = vault.read_secret(template_secret.vault_key) or template_secret.default
if secret_value:
environment[e_name] = secret_value
else:
raise InternalServerError(f"Failed to retrieve {template_secret.vault_key} from vault")
elif e_type == "variable":
template_variable = cast(TemplateEnvironmentVariable, environment_entry)
variable_value = os.environ.get(template_variable.variable)
if variable_value is None:
variable_value = template_variable.default
if variable_value:
environment[e_name] = variable_value
else:
raise InternalServerError(
f"Environment variable {template_variable.variable} not found and no default provided. Please set this variable in the environment or provide a default value in the template definition."
)
else:
raise Exception(f"Unknown environment entry type detected [{e_type}]")

Expand Down
10 changes: 9 additions & 1 deletion lib/galaxy/managers/file_source_instances.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@

from galaxy.exceptions import (
Conflict,
InternalServerError,
ItemOwnershipException,
MessageException,
ObjectNotFound,
RequestParameterInvalidException,
RequestParameterMissingException,
Expand Down Expand Up @@ -643,7 +645,13 @@ def template_server_configuration(
oauth2_configuration = get_oauth2_config_or_none(template)
oauth2_scope = None
if oauth2_configuration is not None:
environment = prepare_environment_from_root(template.environment, self._app_vault, self._app_config)
try:
Copy link
Copy Markdown
Member

@mvdbeek mvdbeek Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could just let the exception bubble out, InternalServerError is a MessageException subclass, IIRC it's also logged

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I let the exception bubble out, the message shown to the user will be:

image

Looks rather internal and confusing to the user, which is why I wrapped it.

environment = prepare_environment_from_root(template.environment, self._app_vault, self._app_config)
except InternalServerError as e:
log.exception(
f"Problem preparing environment for template {template_id} version {template_version} - Reason: {str(e)}"
)
raise MessageException("Problem with template configuration - Please contact your administrator.")
user_details = user.config_template_details()
oauth2_client_pair_obj, oauth2_scope = read_oauth2_info_from_configuration(
template.configuration, user_details, environment
Expand Down
40 changes: 39 additions & 1 deletion test/unit/app/managers/test_user_file_sources.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from unittest import SkipTest
from uuid import uuid4

import pytest
from fs.osfs import OSFS

try:
Expand All @@ -16,13 +17,16 @@
from yaml import safe_load

from galaxy.exceptions import (
InternalServerError,
MessageException,
RequestParameterInvalidException,
RequestParameterMissingException,
)
from galaxy.files import FileSourcesUserContext
from galaxy.files.sources import dropbox
from galaxy.files.templates import ConfiguredFileSourceTemplates
from galaxy.files.templates.examples import get_example
from galaxy.managers._config_templates import prepare_environment_from_root
from galaxy.managers.file_source_instances import (
CreateInstancePayload,
FileSourceInstancesManager,
Expand All @@ -43,7 +47,12 @@
)
from galaxy.schema.schema import OAuth2State
from galaxy.util import config_templates
from galaxy.util.config_templates import RawTemplateConfig
from galaxy.util.config_templates import (
RawTemplateConfig,
TemplateEnvironmentEntry,
TemplateEnvironmentSecret,
TemplateEnvironmentVariable,
)
from .base import BaseTestCase

SIMPLE_FILE_SOURCE_NAME = "myfilesource"
Expand Down Expand Up @@ -784,6 +793,35 @@ def test_status_upgrade_invalid(self, tmp_path):
assert "Input should be a valid boolean" in status.template_settings.message
assert status.connection is None

def test_environment_variable_missing_raises_configuration_error(self, tmp_path, monkeypatch):
self._init_managers(tmp_path)
missing_var = "GX_UNIT_TEST_SHOULD_NOT_BE_SET_XYZ123"
monkeypatch.delenv(missing_var, raising=False)
entries: list[TemplateEnvironmentEntry] = [
TemplateEnvironmentVariable(type="variable", name="myvar", variable=missing_var)
]
with pytest.raises(InternalServerError) as exc_info:
prepare_environment_from_root(entries, self.app.vault, self.app)
assert missing_var in str(exc_info.value)

def test_vault_secret_missing_raises_configuration_error(self, tmp_path):
self._init_managers(tmp_path)
entries: list[TemplateEnvironmentEntry] = [
TemplateEnvironmentSecret(type="secret", name="mysec", vault_key="nonexistent/missing_key")
]
with pytest.raises(InternalServerError) as exc_info:
prepare_environment_from_root(entries, self.app.vault, self.app)
assert "nonexistent/missing_key" in str(exc_info.value)

def test_oauth2_template_missing_env_raises_message_exception(self, tmp_path, monkeypatch):
self.init_user_in_database()
self._init_managers(tmp_path, safe_load(get_example("production_dropbox.yml")))
monkeypatch.delenv("GALAXY_DROPBOX_APP_CLIENT_ID", raising=False)
monkeypatch.delenv("GALAXY_DROPBOX_APP_CLIENT_SECRET", raising=False)
with pytest.raises(MessageException) as exc_info:
self.manager.template_oauth2(self.trans, "dropbox", 0)
assert "Please contact your administrator" in str(exc_info.value)

def _init_invalid_upgrade_test_case(self, tmp_path) -> UserFileSourceModel:
version_0 = home_directory_template(tmp_path)
version_0["version"] = 0
Expand Down
Loading