Skip to content

Commit 18a112e

Browse files
refactor: update exception handling to raise directly in inner function
Co-Authored-By: Aaron <AJ> Steers <aj@airbyte.io>
1 parent 64fc46a commit 18a112e

3 files changed

Lines changed: 71 additions & 47 deletions

File tree

airbyte_cdk/cli/airbyte_cdk/_secrets.py

Lines changed: 31 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -132,35 +132,37 @@ def fetch(
132132
)
133133
# Fetch and write secrets
134134
secret_count = 0
135-
failed_secrets: list[str] = []
135+
exceptions = []
136136

137137
for secret in secrets:
138138
secret_file_path = _get_secret_filepath(
139139
secrets_dir=secrets_dir,
140140
secret=secret,
141141
)
142-
error = _write_secret_file(
143-
secret=secret,
144-
client=client,
145-
file_path=secret_file_path,
146-
)
147-
148-
if error:
149-
secret_name = _extract_secret_name(secret.name)
150-
failed_secrets.append(secret_name)
151-
click.echo(f"Failed to retrieve secret '{secret_name}': {error}", err=True)
152-
else:
142+
try:
143+
_write_secret_file(
144+
secret=secret,
145+
client=client,
146+
file_path=secret_file_path,
147+
connector_name=connector_name,
148+
gcp_project_id=gcp_project_id,
149+
)
153150
click.echo(f"Secret written to: {secret_file_path.absolute()!s}", err=True)
154151
secret_count += 1
152+
except ConnectorSecretWithNoValidVersionsError as e:
153+
exceptions.append(e)
154+
click.echo(
155+
f"Failed to retrieve secret '{e.secret_name}': No enabled version found", err=True
156+
)
155157

156-
if secret_count == 0 and not failed_secrets:
158+
if secret_count == 0 and not exceptions:
157159
click.echo(
158160
f"No secrets found for connector: '{connector_name}'",
159161
err=True,
160162
)
161163

162-
if failed_secrets:
163-
error_message = f"Failed to retrieve {len(failed_secrets)} secret(s)"
164+
if exceptions:
165+
error_message = f"Failed to retrieve {len(exceptions)} secret(s)"
164166
click.echo(
165167
style(
166168
error_message,
@@ -169,11 +171,7 @@ def fetch(
169171
err=True,
170172
)
171173
if secret_count == 0:
172-
raise ConnectorSecretWithNoValidVersionsError(
173-
connector_name=connector_name,
174-
secret_names=failed_secrets,
175-
gcp_project_id=gcp_project_id,
176-
)
174+
raise exceptions[0]
177175

178176
if not print_ci_secrets_masks:
179177
return
@@ -333,19 +331,23 @@ def _write_secret_file(
333331
secret: "Secret", # type: ignore
334332
client: "secretmanager.SecretManagerServiceClient", # type: ignore
335333
file_path: Path,
336-
) -> str | None:
334+
connector_name: str,
335+
gcp_project_id: str,
336+
) -> None:
337337
"""Write the most recent enabled version of a secret to a file.
338338
339339
Lists all enabled versions of the secret and selects the most recent one.
340-
Returns an error message if no enabled versions are found.
340+
Raises ConnectorSecretWithNoValidVersionsError if no enabled versions are found.
341341
342342
Args:
343343
secret: The secret to write to a file
344344
client: The Secret Manager client
345345
file_path: The path to write the secret to
346+
connector_name: The name of the connector
347+
gcp_project_id: The GCP project ID
346348
347-
Returns:
348-
str | None: Error message if no enabled version is found, None otherwise
349+
Raises:
350+
ConnectorSecretWithNoValidVersionsError: If no enabled version is found
349351
"""
350352
# List all enabled versions of the secret.
351353
response = client.list_secret_versions(
@@ -358,14 +360,17 @@ def _write_secret_file(
358360

359361
if not versions:
360362
secret_name = _extract_secret_name(secret.name)
361-
return f"No enabled version found for secret: {secret_name}"
363+
raise ConnectorSecretWithNoValidVersionsError(
364+
connector_name=connector_name,
365+
secret_name=secret_name,
366+
gcp_project_id=gcp_project_id,
367+
)
362368

363369
enabled_version = versions[0]
364370

365371
response = client.access_secret_version(name=enabled_version.name)
366372
file_path.write_text(response.payload.data.decode("UTF-8"))
367373
file_path.chmod(0o600) # default to owner read/write only
368-
return None
369374

370375

371376
def _get_secrets_dir(

airbyte_cdk/cli/airbyte_cdk/exceptions.py

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,15 @@ class ConnectorSecretWithNoValidVersionsError(Exception):
99
"""Error when a connector secret has no valid versions."""
1010

1111
connector_name: str
12-
secret_names: list[str]
12+
secret_name: str
1313
gcp_project_id: str
1414

1515
def __str__(self) -> str:
1616
"""Return a string representation of the exception."""
1717
from airbyte_cdk.cli.airbyte_cdk._secrets import _get_secret_url
1818

19-
urls = [
20-
_get_secret_url(secret_name, self.gcp_project_id) for secret_name in self.secret_names
21-
]
22-
urls_str = "\n".join([f"- {url}" for url in urls])
23-
secrets_str = ", ".join(self.secret_names)
19+
url = _get_secret_url(self.secret_name, self.gcp_project_id)
2420
return (
25-
f"No valid versions found for the following secrets in connector '{self.connector_name}': {secrets_str}. "
26-
f"Please check the following URLs for more information:\n{urls_str}"
21+
f"No valid versions found for secret '{self.secret_name}' in connector '{self.connector_name}'. "
22+
f"Please check the following URL for more information:\n- {url}"
2723
)

unit_tests/cli/airbyte_cdk/test_secrets.py

Lines changed: 36 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,13 @@ def test_write_secret_file_with_enabled_version(self, mock_client, mock_secret,
4141
mock_client.access_secret_version.return_value = mock_response
4242

4343
# Call the function
44-
result = _write_secret_file(mock_secret, mock_client, mock_file_path)
44+
_write_secret_file(
45+
secret=mock_secret,
46+
client=mock_client,
47+
file_path=mock_file_path,
48+
connector_name="test-connector",
49+
gcp_project_id="test-project",
50+
)
4551

4652
# Verify that list_secret_versions was called with the correct parameters
4753
mock_client.list_secret_versions.assert_called_once()
@@ -53,17 +59,21 @@ def test_write_secret_file_with_enabled_version(self, mock_client, mock_secret,
5359
# Verify that the file was created with the correct content
5460
assert mock_file_path.read_text() == '{"key": "value"}'
5561

56-
# Verify that no error was returned
57-
assert result is None
58-
5962
def test_write_secret_file_with_no_enabled_versions(
6063
self, mock_client, mock_secret, mock_file_path
6164
):
6265
# Mock list_secret_versions to return an empty list (no enabled versions)
6366
mock_client.list_secret_versions.return_value = []
6467

65-
# Call the function
66-
result = _write_secret_file(mock_secret, mock_client, mock_file_path)
68+
# Call the function and expect an exception
69+
with pytest.raises(ConnectorSecretWithNoValidVersionsError) as excinfo:
70+
_write_secret_file(
71+
secret=mock_secret,
72+
client=mock_client,
73+
file_path=mock_file_path,
74+
connector_name="test-connector",
75+
gcp_project_id="test-project",
76+
)
6777

6878
# Verify that list_secret_versions was called with the correct parameters
6979
mock_client.list_secret_versions.assert_called_once()
@@ -75,10 +85,10 @@ def test_write_secret_file_with_no_enabled_versions(
7585
# Verify that the file was not created
7686
assert not mock_file_path.exists()
7787

78-
# Verify that an error was returned
79-
assert result is not None
80-
assert "No enabled version found for secret" in result
81-
assert "test-secret" in result
88+
# Verify the exception details
89+
assert excinfo.value.secret_name == "test-secret"
90+
assert excinfo.value.connector_name == "test-connector"
91+
assert excinfo.value.gcp_project_id == "test-project"
8292

8393

8494
@patch("airbyte_cdk.cli.airbyte_cdk._secrets._get_gsm_secrets_client")
@@ -118,9 +128,14 @@ def test_fetch_with_some_failed_secrets(
118128
with patch(
119129
"airbyte_cdk.cli.airbyte_cdk._secrets._write_secret_file"
120130
) as mock_write_secret_file:
131+
# First call succeeds, second call raises exception
121132
mock_write_secret_file.side_effect = [
122133
None, # Success for secret1
123-
"No enabled version found for secret: test-secret-2", # Failure for secret2
134+
ConnectorSecretWithNoValidVersionsError(
135+
connector_name="test-connector",
136+
secret_name="test-secret-2",
137+
gcp_project_id="test-project",
138+
), # Failure for secret2
124139
]
125140

126141
# Call the function
@@ -170,8 +185,16 @@ def test_fetch_with_all_failed_secrets(
170185
"airbyte_cdk.cli.airbyte_cdk._secrets._write_secret_file"
171186
) as mock_write_secret_file:
172187
mock_write_secret_file.side_effect = [
173-
"No enabled version found for secret: test-secret-1", # Failure for secret1
174-
"No enabled version found for secret: test-secret-2", # Failure for secret2
188+
ConnectorSecretWithNoValidVersionsError(
189+
connector_name="test-connector",
190+
secret_name="test-secret-1",
191+
gcp_project_id="test-project",
192+
), # Failure for secret1
193+
ConnectorSecretWithNoValidVersionsError(
194+
connector_name="test-connector",
195+
secret_name="test-secret-2",
196+
gcp_project_id="test-project",
197+
), # Failure for secret2
175198
]
176199

177200
# Call the function

0 commit comments

Comments
 (0)