Skip to content

Commit c9388df

Browse files
committed
SNOW-2306184: config refactor - improve connections env parsing
1 parent 9add48f commit c9388df

File tree

3 files changed

+57
-17
lines changed

3 files changed

+57
-17
lines changed

src/snowflake/cli/api/config_ng/sources.py

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -549,23 +549,35 @@ def discover(self, key: Optional[str] = None) -> Dict[str, ConfigValue]:
549549
for env_name, env_value in os.environ.items():
550550
# Check for connection-specific pattern: SNOWFLAKE_CONNECTIONS_<NAME>_<KEY>
551551
if env_name.startswith("SNOWFLAKE_CONNECTIONS_"):
552-
# Extract connection name and config key
552+
# Extract remainder after the prefix
553553
remainder = env_name[len("SNOWFLAKE_CONNECTIONS_") :]
554-
parts = remainder.split("_", 1)
555-
if len(parts) == 2:
556-
conn_name_upper, config_key_upper = parts
557-
conn_name = conn_name_upper.lower()
558-
config_key = config_key_upper.lower()
559-
560-
if config_key in _ENV_CONFIG_KEYS:
561-
full_key = f"connections.{conn_name}.{config_key}"
562-
if key is None or full_key == key:
563-
values[full_key] = ConfigValue(
564-
key=full_key,
565-
value=env_value,
566-
source_name=self.source_name,
567-
raw_value=f"{env_name}={env_value}",
568-
)
554+
555+
# Find the longest matching key suffix from known config keys to
556+
# correctly handle underscores both in connection names and keys
557+
match: tuple[str, str] | None = None
558+
for candidate in sorted(_ENV_CONFIG_KEYS, key=len, reverse=True):
559+
key_suffix = "_" + candidate.upper()
560+
if remainder.endswith(key_suffix):
561+
conn_name_upper = remainder[: -len(key_suffix)]
562+
if conn_name_upper: # ensure non-empty connection name
563+
match = (conn_name_upper, candidate)
564+
break
565+
566+
if not match:
567+
# Unknown/unsupported key suffix; ignore
568+
continue
569+
570+
conn_name_upper, config_key = match
571+
conn_name = conn_name_upper.lower()
572+
573+
full_key = f"connections.{conn_name}.{config_key}"
574+
if key is None or full_key == key:
575+
values[full_key] = ConfigValue(
576+
key=full_key,
577+
value=env_value,
578+
source_name=self.source_name,
579+
raw_value=f"{env_name}={env_value}",
580+
)
569581

570582
return values
571583

src/snowflake/cli/api/config_provider.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -603,7 +603,7 @@ def _get_file_based_connections(self) -> dict:
603603
connections_prefix = "connections."
604604

605605
assert self._resolver is not None
606-
for source in self._resolver._sources: # noqa: SLF001
606+
for source in self._resolver.get_sources():
607607
if source.source_name not in file_source_names:
608608
continue
609609

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Copyright (c) 2024 Snowflake Inc.
2+
3+
"""Focused tests for environment variable parsing in config_ng."""
4+
5+
6+
def test_connection_specific_env_with_underscores(config_ng_setup):
7+
"""Connection names containing underscores should parse correctly.
8+
9+
Also validate keys that themselves contain underscores (e.g., PRIVATE_KEY_PATH).
10+
"""
11+
12+
env_vars = {
13+
# Connection-specific variables for connection name with underscores
14+
"SNOWFLAKE_CONNECTIONS_DEV_US_EAST_ACCOUNT": "from-specific",
15+
"SNOWFLAKE_CONNECTIONS_DEV_US_EAST_PRIVATE_KEY_PATH": "/tmp/example_key.pem",
16+
# General env remains available for other flat keys
17+
"SNOWFLAKE_SCHEMA": "general-schema",
18+
}
19+
20+
with config_ng_setup(env_vars=env_vars):
21+
from snowflake.cli.api.config import get_connection_dict
22+
23+
conn = get_connection_dict("dev_us_east")
24+
25+
assert conn["account"] == "from-specific"
26+
assert conn["private_key_path"] == "/tmp/example_key.pem"
27+
# Ensure general env still contributes flat keys
28+
assert conn["schema"] == "general-schema"

0 commit comments

Comments
 (0)