Skip to content

Commit f21f4e6

Browse files
committed
fallback to downloading dockerfile definitions from github
1 parent 2c032bd commit f21f4e6

File tree

2 files changed

+96
-182
lines changed

2 files changed

+96
-182
lines changed

airbyte_cdk/utils/docker.py

Lines changed: 96 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,10 @@
1212
from pathlib import Path
1313

1414
import click
15+
import requests
1516

1617
from airbyte_cdk.models.connector_metadata import ConnectorLanguage, MetadataFile
1718
from airbyte_cdk.utils.connector_paths import resolve_airbyte_repo_root
18-
from airbyte_cdk.utils.docker_image_templates import (
19-
DOCKERIGNORE_TEMPLATE,
20-
JAVA_CONNECTOR_DOCKERFILE_TEMPLATE,
21-
MANIFEST_ONLY_DOCKERFILE_TEMPLATE,
22-
PYTHON_CONNECTOR_DOCKERFILE_TEMPLATE,
23-
)
2419

2520

2621
@dataclass(kw_only=True)
@@ -165,20 +160,36 @@ def build_connector_image(
165160
ConnectorImageBuildError: If the image build or tag operation fails.
166161
"""
167162
connector_kebab_name = connector_name
168-
connector_snake_name = connector_kebab_name.replace("-", "_")
169163

170164
if dockerfile_override:
171165
dockerfile_path = dockerfile_override
172166
else:
173167
dockerfile_path = connector_directory / "build" / "docker" / "Dockerfile"
174-
dockerfile_path.write_text(
175-
get_dockerfile_template(
176-
metadata,
177-
connector_directory,
178-
)
179-
)
180168
dockerignore_path = connector_directory / "build" / "docker" / "Dockerfile.dockerignore"
181-
dockerignore_path.write_text(DOCKERIGNORE_TEMPLATE)
169+
try:
170+
dockerfile_text, dockerignore_text = get_dockerfile_templates(
171+
metadata=metadata,
172+
connector_directory=connector_directory,
173+
)
174+
except FileNotFoundError:
175+
# If the Dockerfile and .dockerignore are not found in the connector directory,
176+
# download the templates from the Airbyte repo. This is a fallback
177+
# in case the Airbyte repo not checked out locally.
178+
try:
179+
dockerfile_text, dockerignore_text = _download_dockerfile_defs(
180+
connector_language=metadata.data.language,
181+
)
182+
except requests.HTTPError as e:
183+
raise ConnectorImageBuildError(
184+
build_args=[],
185+
error_text=(
186+
"Could not locate local dockerfile templates and "
187+
f"failed to download Dockerfile templates from github: {e}"
188+
),
189+
) from e
190+
191+
dockerfile_path.write_text(dockerfile_text)
192+
dockerignore_path.write_text(dockerignore_text)
182193

183194
extra_build_script: str = ""
184195
build_customization_path = connector_directory / "build_customization.py"
@@ -249,18 +260,67 @@ def build_connector_image(
249260
sys.exit(0)
250261

251262

252-
def get_dockerfile_template(
263+
def _download_dockerfile_defs(
264+
connector_language: ConnectorLanguage,
265+
) -> tuple[str, str]:
266+
"""Download the Dockerfile and .dockerignore templates for the specified connector language.
267+
268+
We use the requests library to download from the master branch hosted on GitHub.
269+
270+
Args:
271+
connector_language: The language of the connector.
272+
273+
Returns:
274+
A tuple containing the Dockerfile and .dockerignore templates as strings.
275+
276+
Raises:
277+
ValueError: If the connector language is not supported.
278+
requests.HTTPError: If the download fails.
279+
"""
280+
print("Downloading Dockerfile and .dockerignore templates from GitHub...")
281+
# Map ConnectorLanguage to template directory
282+
language_to_template_suffix = {
283+
ConnectorLanguage.PYTHON: "python-connector",
284+
ConnectorLanguage.JAVA: "java-connector",
285+
ConnectorLanguage.MANIFEST_ONLY: "manifest-only-connector",
286+
}
287+
288+
if connector_language not in language_to_template_suffix:
289+
raise ValueError(f"Unsupported connector language: {connector_language}")
290+
291+
template_suffix = language_to_template_suffix[connector_language]
292+
base_url = f"https://github.com/airbytehq/airbyte/raw/master/docker-images/"
293+
294+
dockerfile_url = f"{base_url}/Dockerfile.{template_suffix}"
295+
dockerignore_url = f"{base_url}/Dockerfile.{template_suffix}.dockerignore"
296+
297+
dockerfile_resp = requests.get(dockerfile_url)
298+
dockerfile_resp.raise_for_status()
299+
dockerfile_text = dockerfile_resp.text
300+
301+
dockerignore_resp = requests.get(dockerignore_url)
302+
dockerignore_resp.raise_for_status()
303+
dockerignore_text = dockerignore_resp.text
304+
305+
return dockerfile_text, dockerignore_text
306+
307+
308+
def get_dockerfile_templates(
253309
metadata: MetadataFile,
254310
connector_directory: Path,
255-
) -> str:
311+
) -> tuple[str, str]:
256312
"""Get the Dockerfile template for the connector.
257313
258314
Args:
259315
metadata: The metadata of the connector.
260316
connector_name: The name of the connector.
261317
318+
Raises:
319+
ValueError: If the connector language is not supported.
320+
FileNotFoundError: If the Dockerfile or .dockerignore is not found.
321+
262322
Returns:
263-
The Dockerfile template as a string.
323+
A tuple containing the Dockerfile and .dockerignore templates as strings.
264324
"""
265325
if metadata.data.language not in [
266326
ConnectorLanguage.PYTHON,
@@ -272,38 +332,28 @@ def get_dockerfile_template(
272332
"Please check the connector's metadata file."
273333
)
274334

275-
try:
276-
airbyte_repo_root = resolve_airbyte_repo_root(
277-
from_dir=connector_directory,
335+
airbyte_repo_root = resolve_airbyte_repo_root(
336+
from_dir=connector_directory,
337+
)
338+
# airbyte_repo_root successfully resolved
339+
dockerfile_path = (
340+
airbyte_repo_root / "docker-images" / f"Dockerfile.{metadata.data.language.value}-connector"
341+
)
342+
dockerignore_path = (
343+
airbyte_repo_root
344+
/ "docker-images"
345+
/ f"Dockerfile.{metadata.data.language.value}-connector.dockerignore"
346+
)
347+
if not dockerfile_path.exists():
348+
raise FileNotFoundError(
349+
f"Dockerfile for {metadata.data.language.value} connector not found at {dockerfile_path}"
278350
)
279-
# airbyte_repo_root successfully resolved
280-
dockerfile_path = (
281-
airbyte_repo_root
282-
/ "docker-images"
283-
/ f"Dockerfile.{metadata.data.language.value}-connector"
351+
if not dockerignore_path.exists():
352+
raise FileNotFoundError(
353+
f".dockerignore for {metadata.data.language.value} connector not found at {dockerignore_path}"
284354
)
285-
if not dockerfile_path.exists():
286-
raise FileNotFoundError(
287-
f"Dockerfile for {metadata.data.language.value} connector not found at {dockerfile_path}"
288-
)
289-
return dockerfile_path.read_text()
290-
291-
except FileNotFoundError:
292-
raise
293-
if metadata.data.language == ConnectorLanguage.PYTHON:
294-
return PYTHON_CONNECTOR_DOCKERFILE_TEMPLATE
295-
296-
if metadata.data.language == ConnectorLanguage.MANIFEST_ONLY:
297-
return MANIFEST_ONLY_DOCKERFILE_TEMPLATE
298-
299-
if metadata.data.language == ConnectorLanguage.JAVA:
300-
return JAVA_CONNECTOR_DOCKERFILE_TEMPLATE
301355

302-
# Should not be reachable but we include to make linter happy:
303-
raise ValueError(
304-
f"Unsupported connector language: {metadata.data.language}. "
305-
"Please check the connector's metadata file."
306-
)
356+
return dockerfile_path.read_text(), dockerignore_path.read_text()
307357

308358

309359
def run_docker_command(

airbyte_cdk/utils/docker_image_templates.py

Lines changed: 0 additions & 136 deletions
This file was deleted.

0 commit comments

Comments
 (0)