Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
davidsanfal committed Apr 30, 2024
1 parent 8056359 commit 3803ac5
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 108 deletions.
18 changes: 13 additions & 5 deletions conan/cli/commands/create.py
Expand Up @@ -67,11 +67,19 @@ def create(conan_api, parser, *args):

print_profiles(profile_host, profile_build)
if profile_host.runner and not os.environ.get("CONAN_RUNNER_ENVIRONMENT"):
return {
'docker': DockerRunner,
'ssh': SSHRunner,
'wsl': WSLRunner,
}[profile_host.runner.get('type')](conan_api, 'create', profile_host, profile_build, args, raw_args).run()
try:
runner_type = profile_host.runner['type']
except KeyError:
raise ConanException(f"Invalid runner configuration. 'type' field must be defined")
try:
runner_instance = {
'docker': DockerRunner,
'ssh': SSHRunner,
'wsl': WSLRunner,
}[runner_type]
except KeyError:
raise ConanException(f"Invalid runner type '{runner_type}'. The allowed values are 'docker', 'ssh' or 'wsl'")
return runner_instance(conan_api, 'create', profile_host, profile_build, args, raw_args).run()

if args.build is not None and args.build_test is None:
args.build_test = args.build
Expand Down
31 changes: 11 additions & 20 deletions conan/internal/runner/docker.py
Expand Up @@ -51,7 +51,7 @@ def _instans_or_error(value, obj):
)


def docker_info(msg, error=False):
def _docker_info(msg, error=False):
fg=Color.BRIGHT_MAGENTA
if error:
fg=Color.BRIGHT_RED
Expand All @@ -60,15 +60,6 @@ def docker_info(msg, error=False):
ConanOutput().status('└'+'─'*(2+len(msg))+'┘\n', fg=fg)


def list_patterns(cache_info):
_pattern = []
for reference, info in cache_info.items():
for revisions in info.get('revisions', {}).values():
for package in revisions.get('packages').keys():
_pattern.append(f'{reference}:{package}')
return _pattern


class DockerRunner:
def __init__(self, conan_api, command, host_profile, build_profile, args, raw_args):
import docker
Expand All @@ -80,7 +71,7 @@ def __init__(self, conan_api, command, host_profile, build_profile, args, raw_ar
except:
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'")
"\n - Run 'pip install pip install conan[runners]'")
self.conan_api = conan_api
self.build_profile = build_profile
self.args = args
Expand Down Expand Up @@ -125,21 +116,21 @@ def run(self):
run conan inside a Docker continer
"""
if self.dockerfile:
docker_info(f'Building the Docker image: {self.image}')
_docker_info(f'Building the Docker image: {self.image}')
self.build_image()
volumes, environment = self.create_runner_environment()
error = False
try:
if self.docker_client.containers.list(all=True, filters={'name': self.name}):
docker_info('Starting the docker container')
_docker_info('Starting the docker container')
self.container = self.docker_client.containers.get(self.name)
self.container.start()
else:
if self.configfile.run.environment:
environment.update(self.configfile.run.environment)
if self.configfile.run.volumes:
volumes.update(self.configfile.run.volumes)
docker_info('Creating the docker container')
_docker_info('Creating the docker container')
self.container = self.docker_client.containers.run(
self.image,
"/bin/bash -c 'while true; do sleep 30; done;'",
Expand All @@ -152,7 +143,7 @@ def run(self):
security_opt=self.configfile.run.security_opt,
detach=True,
auto_remove=False)
docker_info(f'Container {self.name} running')
_docker_info(f'Container {self.name} running')
except Exception as e:
raise ConanException(f'Imposible to run the container "{self.name}" with image "{self.image}"'
f'\n\n{str(e)}')
Expand All @@ -170,10 +161,10 @@ def run(self):
finally:
if self.container:
error_prefix = 'ERROR: ' if error else ''
docker_info(f'{error_prefix}Stopping container', error)
_docker_info(f'{error_prefix}Stopping container', error)
self.container.stop()
if self.remove:
docker_info(f'{error_prefix}Removing container', error)
_docker_info(f'{error_prefix}Removing container', error)
self.container.remove()

def build_image(self):
Expand All @@ -200,7 +191,7 @@ def build_image(self):

def run_command(self, command, log=True):
if log:
docker_info(f'Running in container: "{command}"')
_docker_info(f'Running in container: "{command}"')
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 = '', ''
Expand Down Expand Up @@ -248,7 +239,7 @@ def create_runner_environment(self):

if self.cache == 'copy':
tgz_path = os.path.join(self.abs_runner_home_path, 'local_cache_save.tgz')
docker_info(f'Save host cache in: {tgz_path}')
_docker_info(f'Save host cache in: {tgz_path}')
self.conan_api.cache.save(self.conan_api.list.select(ListPattern("*:*")), tgz_path)
return volumes, environment

Expand All @@ -274,5 +265,5 @@ def update_local_cache(self):
self.run_command('conan list --graph=create.json --graph-binaries=build --format=json > pkglist.json', log=False)
self.run_command('conan cache save --list=pkglist.json --file "'+self.abs_docker_path+'"/.conanrunner/docker_cache_save.tgz')
tgz_path = os.path.join(self.abs_runner_home_path, 'docker_cache_save.tgz')
docker_info(f'Restore host cache from: {tgz_path}')
_docker_info(f'Restore host cache from: {tgz_path}')
package_list = self.conan_api.cache.restore(tgz_path)
104 changes: 21 additions & 83 deletions conans/test/integration/command/runner_test.py
Expand Up @@ -87,36 +87,20 @@ def test_create_docker_runner_dockerfile_folder_path():
remove=True
""")

conanfile = textwrap.dedent("""
from conan import ConanFile
class MyTest(ConanFile):
name = "pkg"
version = "0.2"
settings = "build_type", "compiler"
author = "John Doe"
license = "MIT"
url = "https://foo.bar.baz"
homepage = "https://foo.bar.site"
topics = "foo", "bar", "qux"
provides = "libjpeg", "libjpg"
deprecated = "other-pkg"
options = {"shared": [True, False], "fPIC": [True, False]}
default_options = {"shared": False, "fPIC": True}
""")
client.save({"conanfile.py": conanfile, "host_copy": profile_host_copy, "host_clean": profile_host_clean, "build": profile_build})
client.save({"host_copy": profile_host_copy, "host_clean": profile_host_clean, "build": profile_build})
client.run("new cmake_lib -d name=pkg -d version=0.2")
client.run("create . -pr:h host_copy -pr:b build")

assert "Restore: pkg/0.2" in client.out
assert "Restore: pkg/0.2:a0826e5ee3b340fcc7a8ccde40224e3562316307" in client.out
assert "Restore: pkg/0.2:a0826e5ee3b340fcc7a8ccde40224e3562316307 metadata" in client.out
assert "Restore: pkg/0.2:8631cf963dbbb4d7a378a64a6fd1dc57558bc2fe" in client.out
assert "Restore: pkg/0.2:8631cf963dbbb4d7a378a64a6fd1dc57558bc2fe metadata" in client.out
assert "Removing container" in client.out

client.run("create . -pr:h host_clean -pr:b build")

assert "Restore: pkg/0.2" in client.out
assert "Restore: pkg/0.2:a0826e5ee3b340fcc7a8ccde40224e3562316307" in client.out
assert "Restore: pkg/0.2:a0826e5ee3b340fcc7a8ccde40224e3562316307 metadata" in client.out
assert "Restore: pkg/0.2:8631cf963dbbb4d7a378a64a6fd1dc57558bc2fe" in client.out
assert "Restore: pkg/0.2:8631cf963dbbb4d7a378a64a6fd1dc57558bc2fe metadata" in client.out
assert "Removing container" in client.out


Expand Down Expand Up @@ -154,29 +138,13 @@ def test_create_docker_runner_dockerfile_file_path():
cache=copy
remove=True
""")
conanfile = textwrap.dedent("""
from conan import ConanFile
class MyTest(ConanFile):
name = "pkg"
version = "0.2"
settings = "build_type", "compiler"
author = "John Doe"
license = "MIT"
url = "https://foo.bar.baz"
homepage = "https://foo.bar.site"
topics = "foo", "bar", "qux"
provides = "libjpeg", "libjpg"
deprecated = "other-pkg"
options = {"shared": [True, False], "fPIC": [True, False]}
default_options = {"shared": False, "fPIC": True}
""")
client.save({"conanfile.py": conanfile, "host": profile_host, "build": profile_build})
client.save({"host": profile_host, "build": profile_build})
client.run("new cmake_lib -d name=pkg -d version=0.2")
client.run("create . -pr:h host -pr:b build")

print(client.out)
assert "Restore: pkg/0.2" in client.out
assert "Restore: pkg/0.2:a0826e5ee3b340fcc7a8ccde40224e3562316307" in client.out
assert "Restore: pkg/0.2:a0826e5ee3b340fcc7a8ccde40224e3562316307 metadata" in client.out
assert "Restore: pkg/0.2:8631cf963dbbb4d7a378a64a6fd1dc57558bc2fe" in client.out
assert "Restore: pkg/0.2:8631cf963dbbb4d7a378a64a6fd1dc57558bc2fe metadata" in client.out
assert "Removing container" in client.out


Expand Down Expand Up @@ -280,29 +248,14 @@ def test_create_docker_runner_profile_abs_path():
cache=copy
remove=True
""")
conanfile = textwrap.dedent("""
from conan import ConanFile
class MyTest(ConanFile):
name = "pkg"
version = "0.2"
settings = "build_type", "compiler"
author = "John Doe"
license = "MIT"
url = "https://foo.bar.baz"
homepage = "https://foo.bar.site"
topics = "foo", "bar", "qux"
provides = "libjpeg", "libjpg"
deprecated = "other-pkg"
options = {"shared": [True, False], "fPIC": [True, False]}
default_options = {"shared": False, "fPIC": True}
""")
client.save({"conanfile.py": conanfile, "host": profile_host, "build": profile_build})

client.save({"host": profile_host, "build": profile_build})
client.run("new cmake_lib -d name=pkg -d version=0.2")
client.run(f"create . -pr:h '{os.path.join(client.current_folder, 'host')}' -pr:b '{os.path.join(client.current_folder, 'build')}'")

assert "Restore: pkg/0.2" in client.out
assert "Restore: pkg/0.2:a0826e5ee3b340fcc7a8ccde40224e3562316307" in client.out
assert "Restore: pkg/0.2:a0826e5ee3b340fcc7a8ccde40224e3562316307 metadata" in client.out
assert "Restore: pkg/0.2:8631cf963dbbb4d7a378a64a6fd1dc57558bc2fe" in client.out
assert "Restore: pkg/0.2:8631cf963dbbb4d7a378a64a6fd1dc57558bc2fe metadata" in client.out
assert "Removing container" in client.out


Expand Down Expand Up @@ -347,27 +300,12 @@ def test_create_docker_runner_profile_abs_path_from_configfile():
cache=copy
remove=True
""")
conanfile = textwrap.dedent("""
from conan import ConanFile
class MyTest(ConanFile):
name = "pkg"
version = "0.2"
settings = "build_type", "compiler"
author = "John Doe"
license = "MIT"
url = "https://foo.bar.baz"
homepage = "https://foo.bar.site"
topics = "foo", "bar", "qux"
provides = "libjpeg", "libjpg"
deprecated = "other-pkg"
options = {"shared": [True, False], "fPIC": [True, False]}
default_options = {"shared": False, "fPIC": True}
""")
client.save({"conanfile.py": conanfile, "host": profile_host, "build": profile_build})

client.save({"host": profile_host, "build": profile_build})
client.run("new cmake_lib -d name=pkg -d version=0.2")
client.run(f"create . -pr:h '{os.path.join(client.current_folder, 'host')}' -pr:b '{os.path.join(client.current_folder, 'build')}'")

assert "Restore: pkg/0.2" in client.out
assert "Restore: pkg/0.2:a0826e5ee3b340fcc7a8ccde40224e3562316307" in client.out
assert "Restore: pkg/0.2:a0826e5ee3b340fcc7a8ccde40224e3562316307 metadata" in client.out
assert "Restore: pkg/0.2:8631cf963dbbb4d7a378a64a6fd1dc57558bc2fe" in client.out
assert "Restore: pkg/0.2:8631cf963dbbb4d7a378a64a6fd1dc57558bc2fe metadata" in client.out
assert "Removing container" in client.out

0 comments on commit 3803ac5

Please sign in to comment.