Skip to content

Commit

Permalink
new docker exec added
Browse files Browse the repository at this point in the history
  • Loading branch information
davidsanfal committed Mar 11, 2024
1 parent dd498c7 commit 69bd33e
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 41 deletions.
4 changes: 2 additions & 2 deletions conan/cli/commands/create.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,11 @@ def create(conan_api, parser, *args):
args.build_require)

print_profiles(profile_host, profile_build)
if profile_build.runner and not os.environ.get("CONAN_RUNNER_ENVIRONMENT"):
if profile_host.runner and not os.environ.get("CONAN_RUNNER_ENVIRONMENT"):
return {
'docker': DockerRunner,
'ssh': SSHRunner
}[profile_build.runner.get('type')](conan_api, 'create', profile_host, args, raw_args).run()
}[profile_host.runner.get('type')](conan_api, 'create', profile_host, args, raw_args).run()

if args.build is not None and args.build_test is None:
args.build_test = args.build
Expand Down
6 changes: 6 additions & 0 deletions conan/internal/runner/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
class RunnerExection(Exception):
def __init__(self, *args, **kwargs):
self.command = kwargs.pop("command", None)
self.stdout_log = kwargs.pop("stdout_log", None)
self.stderr_log = kwargs.pop("stderr_log", None)
super(RunnerExection, self).__init__(*args, **kwargs)
73 changes: 49 additions & 24 deletions conan/internal/runner/docker.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import os
import json
import platform
import shutil
from conan.api.model import ListPattern
from conan.api.output import ConanOutput
from conan.api.conan_api import ConfigAPI
from conan.cli import make_abs_path
from conan.internal.runner import RunnerExection
from conans.client.profile_loader import ProfileLoader
from conans.errors import ConanException

Expand Down Expand Up @@ -33,7 +35,9 @@ def __init__(self, conan_api, command, profile, args, raw_args):
self.docker_api = docker.APIClient()
docker.api.build.process_dockerfile = lambda dockerfile, path: ('Dockerfile', dockerfile)
except:
raise ConanException("Docker Client failed to initialize. Check if it is installed and running")
raise ConanException("Docker Client failed to initialize."
"\n - Check if docker is installed and running"
"\n - Run 'pip install docker>=5.0.0, <=5.0.3'")
self.conan_api = conan_api
self.args = args
self.abs_host_path = make_abs_path(args.path)
Expand All @@ -58,29 +62,35 @@ def run(self):
"""
run conan inside a Docker continer
"""
docker_info(f'Building the Docker image: {self.image}')
if self.dockerfile:
docker_info(f'Building the Docker image: {self.image}')
self.build_image()
volumes, environment = self.create_runner_environment()
docker_info('Creating the docker container')
if self.docker_client.containers.list(all=True, filters={'name': self.name}):
self.container = self.docker_client.containers.get(self.name)
self.container.start()
else:
self.container = self.docker_client.containers.run(
self.image,
"/bin/bash -c 'while true; do sleep 30; done;'",
name=self.name,
volumes=volumes,
environment=environment,
detach=True,
auto_remove=False)
try:
if self.docker_client.containers.list(all=True, filters={'name': self.name}):
docker_info('Starting the docker container')
self.container = self.docker_client.containers.get(self.name)
self.container.start()
else:
docker_info('Creating the docker container')
self.container = self.docker_client.containers.run(
self.image,
"/bin/bash -c 'while true; do sleep 30; done;'",
name=self.name,
volumes=volumes,
environment=environment,
detach=True,
auto_remove=False)
except Exception as e:
raise ConanException(f'Imposible to run the container "{self.name}" with image "{self.image}"'
f'\n\n{str(e)}')
try:
self.init_container()
self.run_command(self.command)
self.update_local_cache()
except:
ConanOutput().error(f'Something went wrong running "{self.command}" inside the container')
except RunnerExection as e:
raise ConanException(f'"{e.command}" inside docker fail'
f'\n\nLast command output: {str(e.stdout_log)}')
finally:
if self.container:
docker_info('Stopping container')
Expand Down Expand Up @@ -108,14 +118,29 @@ def build_image(self):
def run_command(self, command, log=True):
if log:
docker_info(f'Running in container: "{command}"')
exec_run = self.container.exec_run(f"/bin/bash -c '{command}'", stream=True, tty=True)
exec_instance = self.docker_api.exec_create(self.container.id, f"/bin/bash -c '{command}'", tty=True)
exec_output = self.docker_api.exec_start(exec_instance['Id'], tty=True, stream=True, demux=True,)
stderr_log, stdout_log = '', ''
try:
while True:
chunk = next(exec_run.output).decode('utf-8', errors='ignore').strip()
if log:
ConanOutput().info(chunk)
except StopIteration:
pass
for (stdout_out, stderr_out) in exec_output:
if stdout_out is not None:
stdout_log += stdout_out.decode('utf-8', errors='ignore').strip()
if log:
ConanOutput().info(stdout_out.decode('utf-8', errors='ignore').strip())
if stderr_out is not None:
stderr_log += stderr_out.decode('utf-8', errors='ignore').strip()
if log:
ConanOutput().info(stderr_out.decode('utf-8', errors='ignore').strip())
except Exception as e:
if platform.system() == 'Windows':
import pywintypes
if isinstance(e, pywintypes.error):
pass
else:
raise e
exit_metadata = self.docker_api.exec_inspect(exec_instance['Id'])
if exit_metadata['Running'] or exit_metadata['ExitCode'] > 0:
raise RunnerExection(command=command, stdout_log=stdout_log, stderr_log=stderr_log)

def create_runner_environment(self):
volumes = {self.abs_host_path: {'bind': self.abs_docker_path, 'mode': 'rw'}}
Expand Down
1 change: 0 additions & 1 deletion conans/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,3 @@ fasteners>=0.15
distro>=1.4.0, <=1.8.0; sys_platform == 'linux' or sys_platform == 'linux2'
Jinja2>=3.0, <4.0.0
python-dateutil>=2.8.0, <3
docker>=5.0.0, <=5.0.3
14 changes: 0 additions & 14 deletions conans/test/integration/command/runner_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,6 @@ def test_create_docker_runner_dockerfile_folder_path():
compiler.libcxx=libstdc++11
compiler.version=11
os=Linux
[runner]
type=docker
dockerfile={dockerfile_path()}
docker_build_path={conan_base_path()}
image=conan-runner-default-test
cache=copy
remove=True
""")
profile_host = textwrap.dedent(f"""\
[settings]
Expand Down Expand Up @@ -117,13 +110,6 @@ def test_create_docker_runner_dockerfile_file_path():
compiler.libcxx=libstdc++11
compiler.version=11
os=Linux
[runner]
type=docker
dockerfile={dockerfile_path("Dockerfile_test")}
docker_build_path={conan_base_path()}
image=conan-runner-default-test
cache=copy
remove=True
""")
profile_host = textwrap.dedent(f"""\
[settings]
Expand Down

0 comments on commit 69bd33e

Please sign in to comment.