Skip to content

Commit 49d28f0

Browse files
authored
airbyte-ci: correct mounted volumes ownership (#51582)
1 parent 5335bd2 commit 49d28f0

File tree

6 files changed

+28
-16
lines changed

6 files changed

+28
-16
lines changed

airbyte-ci/connectors/pipelines/README.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -854,7 +854,8 @@ airbyte-ci connectors --language=low-code migrate-to-manifest-only
854854

855855
| Version | PR | Description |
856856
| ------- | ---------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
857-
| 4.48.8 | [#51609](https://github.com/airbytehq/airbyte/pull/51609) | Fix typo in `migrate-to-inline-schemas` command |
857+
| 4.48.9 | [#51609](https://github.com/airbytehq/airbyte/pull/51609) | Fix ownership of shared cache volume for non root connectors |
858+
| 4.48.8 | [#51582](https://github.com/airbytehq/airbyte/pull/51582) | Fix typo in `migrate-to-inline-schemas` command |
858859
| 4.48.7 | [#51579](https://github.com/airbytehq/airbyte/pull/51579) | Give back the ownership of /tmp to the original user on finalize build |
859860
| 4.48.6 | [#51577](https://github.com/airbytehq/airbyte/pull/51577) | Run finalize build scripts as root |
860861
| 4.48.5 | [#49827](https://github.com/airbytehq/airbyte/pull/49827) | Bypasses CI checks for promoted release candidate PRs. |

airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/build_image/steps/python_connectors.py

+2
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,8 @@ async def _build_from_base_image(self, platform: Platform) -> Container:
9191

9292
connector_container = build_customization.apply_airbyte_entrypoint(base_connector_container, self.context.connector)
9393
customized_connector = await build_customization.post_install_hooks(self.context.connector, connector_container, self.logger)
94+
# Make sure the user has access to /tmp
95+
customized_connector = customized_connector.with_exec(["chown", "-R", f"{user}:{user}", "/tmp"])
9496
return customized_connector.with_user(user)
9597

9698
async def _build_from_dockerfile(self, platform: Platform) -> Container:

airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/steps/python_connectors.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ async def _run(self, connector_under_test: Container) -> StepResult:
8383
pytest_command = self.get_pytest_command(test_config_file_name)
8484

8585
if self.bind_to_docker_host:
86-
test_environment = pipelines.dagger.actions.system.docker.with_bound_docker_host(self.context, test_environment)
86+
test_environment = await pipelines.dagger.actions.system.docker.with_bound_docker_host(self.context, test_environment)
8787

8888
test_execution = test_environment.with_exec(pytest_command)
8989

airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/steps/gradle.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ async def _run(self, *args: Any, **kwargs: Any) -> StepResult:
201201
gradle_container = gradle_container.with_(await secrets.mounted_connector_secrets(self.context, secrets_dir, self.secrets))
202202
if self.bind_to_docker_host:
203203
# If this GradleTask subclass needs docker, then install it and bind it to the existing global docker host container.
204-
gradle_container = pipelines.dagger.actions.system.docker.with_bound_docker_host(self.context, gradle_container)
204+
gradle_container = await pipelines.dagger.actions.system.docker.with_bound_docker_host(self.context, gradle_container)
205205
# This installation should be cheap, as the package has already been downloaded, and its dependencies are already installed.
206206
gradle_container = gradle_container.with_exec(["yum", "install", "-y", "docker"], use_entrypoint=True)
207207

airbyte-ci/connectors/pipelines/pipelines/dagger/actions/system/docker.py

+21-12
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33
#
44

55
import json
6+
import logging
7+
import platform
68
import uuid
7-
from typing import Callable, Dict, List, Optional, Union
9+
from typing import Any, Callable, Coroutine, Dict, List, Optional, Union
810

911
from dagger import Client, Container, File, Service
1012
from dagger import Secret as DaggerSecret
@@ -56,13 +58,17 @@ def get_base_dockerd_container(dagger_client: Client) -> Container:
5658
)
5759
)
5860
# Expose the docker host port.
61+
.with_exec(["adduser", "-u", "1000", "-S", "-H", "airbyte"])
5962
.with_exposed_port(DOCKER_HOST_PORT)
6063
# We cache /tmp for file sharing between client and daemon.
61-
.with_mounted_cache("/tmp", dagger_client.cache_volume(DOCKER_TMP_VOLUME_NAME))
64+
.with_mounted_cache("/tmp", dagger_client.cache_volume(DOCKER_TMP_VOLUME_NAME), owner="airbyte")
65+
.with_exec(["chmod", "777", "/tmp"])
6266
)
6367

6468
# We cache /var/lib/docker to avoid downloading images and layers multiple times.
65-
base_container = base_container.with_mounted_cache("/var/lib/docker", dagger_client.cache_volume(DOCKER_VAR_LIB_VOLUME_NAME))
69+
base_container = base_container.with_mounted_cache(
70+
"/var/lib/docker", dagger_client.cache_volume(DOCKER_VAR_LIB_VOLUME_NAME), owner="airbyte"
71+
)
6672
return base_container
6773

6874

@@ -75,8 +81,10 @@ def get_daemon_config_json(registry_mirror_url: Optional[str] = None) -> str:
7581
Returns:
7682
str: The json representation of the docker daemon config.
7783
"""
84+
storage_driver = "vfs" if platform.system() == "Darwin" else STORAGE_DRIVER
85+
logging.info(f"Using storage driver: {storage_driver}")
7886
daemon_config: Dict[str, Union[List[str], str]] = {
79-
"storage-driver": STORAGE_DRIVER,
87+
"storage-driver": storage_driver,
8088
}
8189
if registry_mirror_url:
8290
daemon_config["registry-mirrors"] = ["http://" + registry_mirror_url]
@@ -152,7 +160,7 @@ def with_global_dockerd_service(
152160
).as_service()
153161

154162

155-
def with_bound_docker_host(
163+
async def with_bound_docker_host(
156164
context: ConnectorContext,
157165
container: Container,
158166
) -> Container:
@@ -165,21 +173,22 @@ def with_bound_docker_host(
165173
Container: The container bound to the docker host.
166174
"""
167175
assert context.dockerd_service is not None
176+
current_user = (await container.with_exec(["whoami"]).stdout()).strip()
168177
return (
169178
container.with_env_variable("DOCKER_HOST", f"tcp://{DOCKER_HOST_NAME}:{DOCKER_HOST_PORT}")
170179
.with_service_binding(DOCKER_HOST_NAME, context.dockerd_service)
171-
.with_mounted_cache("/tmp", context.dagger_client.cache_volume(DOCKER_TMP_VOLUME_NAME))
180+
.with_mounted_cache("/tmp", context.dagger_client.cache_volume(DOCKER_TMP_VOLUME_NAME), owner=current_user)
172181
)
173182

174183

175-
def bound_docker_host(context: ConnectorContext) -> Callable[[Container], Container]:
176-
def bound_docker_host_inner(container: Container) -> Container:
177-
return with_bound_docker_host(context, container)
184+
def bound_docker_host(context: ConnectorContext) -> Callable[[Container], Coroutine[Any, Any, Container]]:
185+
async def bound_docker_host_inner(container: Container) -> Container:
186+
return await with_bound_docker_host(context, container)
178187

179188
return bound_docker_host_inner
180189

181190

182-
def with_docker_cli(context: ConnectorContext) -> Container:
191+
async def with_docker_cli(context: ConnectorContext) -> Container:
183192
"""Create a container with the docker CLI installed and bound to a persistent docker host.
184193
185194
Args:
@@ -189,7 +198,7 @@ def with_docker_cli(context: ConnectorContext) -> Container:
189198
Container: A docker cli container bound to a docker host.
190199
"""
191200
docker_cli = context.dagger_client.container().from_(consts.DOCKER_CLI_IMAGE)
192-
return with_bound_docker_host(context, docker_cli)
201+
return await with_bound_docker_host(context, docker_cli)
193202

194203

195204
async def load_image_to_docker_host(context: ConnectorContext, tar_file: File, image_tag: str) -> str:
@@ -202,7 +211,7 @@ async def load_image_to_docker_host(context: ConnectorContext, tar_file: File, i
202211
"""
203212
# Hacky way to make sure the image is always loaded
204213
tar_name = f"{str(uuid.uuid4())}.tar"
205-
docker_cli = with_docker_cli(context).with_mounted_file(tar_name, tar_file)
214+
docker_cli = (await with_docker_cli(context)).with_mounted_file(tar_name, tar_file)
206215

207216
image_load_output = await docker_cli.with_exec(["docker", "load", "--input", tar_name], use_entrypoint=True).stdout()
208217
# Not tagged images only have a sha256 id the load output shares.

airbyte-ci/connectors/pipelines/pyproject.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
44

55
[tool.poetry]
66
name = "pipelines"
7-
version = "4.48.8"
7+
version = "4.48.9"
88
description = "Packaged maintained by the connector operations team to perform CI for connectors' pipelines"
99
authors = ["Airbyte <[email protected]>"]
1010

0 commit comments

Comments
 (0)