9
9
from pathlib import Path
10
10
from typing import Optional , List , Tuple , Union , Callable
11
11
12
- import docker
13
- import docker .errors
14
- from docker .models .containers import Container , ExecResult
15
- from docker .models .images import Image
12
+ try :
13
+ import docker
14
+ import docker .errors
15
+ except ImportError :
16
+ docker = None
17
+
16
18
from git import Repo
17
19
from requests .exceptions import ConnectionError
18
20
@@ -66,6 +68,9 @@ class DockerBackend(BaseBackend):
66
68
def __init__ (self , ** kwargs ):
67
69
super ().__init__ (** kwargs )
68
70
71
+ if docker is None :
72
+ raise ArcaMisconfigured (ArcaMisconfigured .PACKAGE_MISSING .format ("docker" ))
73
+
69
74
self ._containers = set ()
70
75
self .client = None
71
76
@@ -367,12 +372,14 @@ def get_inherit_image(self) -> Tuple[str, str]:
367
372
368
373
def build_image_from_inherited_image (self , image_name : str , image_tag : str ,
369
374
build_context : Path ,
370
- requirements_file : Optional [Path ]) -> Image :
375
+ requirements_file : Optional [Path ]):
371
376
"""
372
377
Builds a image with installed requirements from the inherited image. (Or just tags the image
373
378
if there are no requirements.)
374
379
375
380
See :meth:`build_image` for parameters descriptions.
381
+
382
+ :rtype: docker.models.images.Image
376
383
"""
377
384
378
385
base_name , base_tag = self .get_inherit_image ()
@@ -429,7 +436,7 @@ def install_dependencies_dockerfile():
429
436
def build_image (self , image_name : str , image_tag : str ,
430
437
build_context : Path ,
431
438
requirements_file : Optional [Path ],
432
- dependencies : Optional [List [str ]]) -> Image :
439
+ dependencies : Optional [List [str ]]):
433
440
""" Builds an image for specific requirements and dependencies, based on the settings.
434
441
435
442
:param image_name: How the image should be named
@@ -438,6 +445,7 @@ def build_image(self, image_name: str, image_tag: str,
438
445
:param requirements_file: Path to the requirements file in the repository (or ``None`` if it doesn't exist)
439
446
:param dependencies: List of dependencies (in the formalized format)
440
447
:return: The Image instance.
448
+ :rtype: docker.models.images.Image
441
449
"""
442
450
if self .inherit_image is not None :
443
451
return self .build_image_from_inherited_image (image_name , image_tag , build_context , requirements_file )
@@ -491,9 +499,10 @@ def install_requirements_dockerfile():
491
499
492
500
return self .get_image (image_name , image_tag )
493
501
494
- def push_to_registry (self , image : Image , image_tag : str ):
502
+ def push_to_registry (self , image , image_tag : str ):
495
503
""" Pushes a local image to a registry based on the ``use_registry_name`` setting.
496
504
505
+ :type image: docker.models.images.Image
497
506
:raise PushToRegistryError: If the push fails.
498
507
"""
499
508
# already tagged, so it's already pushed
@@ -530,21 +539,24 @@ def image_exists(self, image_name, image_tag):
530
539
except docker .errors .ImageNotFound :
531
540
return False
532
541
533
- def get_image (self , image_name , image_tag ) -> Image :
542
+ def get_image (self , image_name , image_tag ):
534
543
""" Returns a :class:`Image <docker.models.images.Image>` instance for the provided name and tag.
544
+
545
+ :rtype: docker.models.images.Image
535
546
"""
536
547
return self .client .images .get (f"{ image_name } :{ image_tag } " )
537
548
538
- def try_pull_image_from_registry (self , image_name , image_tag ) -> Optional [ Image ] :
549
+ def try_pull_image_from_registry (self , image_name , image_tag ):
539
550
"""
540
551
Tries to pull a image with the tag ``image_tag`` from registry set by ``use_registry_name``.
541
552
After the image is pulled, it's tagged with ``image_name``:``image_tag`` so lookup can
542
553
be made locally next time.
543
554
544
555
:return: A :class:`Image <docker.models.images.Image>` instance if the image exists, ``None`` otherwise.
556
+ :rtype: Optional[docker.models.images.Image]
545
557
"""
546
558
try :
547
- image : Image = self .client .images .pull (self .use_registry_name , image_tag )
559
+ image = self .client .images .pull (self .use_registry_name , image_tag )
548
560
except (docker .errors .ImageNotFound , docker .errors .NotFound ): # the image doesn't exist
549
561
logger .info ("Tried to pull %s:%s from a registry, not found" , self .use_registry_name , image_tag )
550
562
return None
@@ -557,11 +569,12 @@ def try_pull_image_from_registry(self, image_name, image_tag) -> Optional[Image]
557
569
558
570
return image
559
571
560
- def container_running (self , container_name ) -> Optional [ Container ] :
572
+ def container_running (self , container_name ):
561
573
"""
562
574
Finds out if a container with name ``container_name`` is running.
563
575
564
576
:return: :class:`Container <docker.models.containers.Container>` if it's running, ``None`` otherwise.
577
+ :rtype: Optional[docker.models.container.Container]
565
578
"""
566
579
filters = {
567
580
"name" : container_name ,
@@ -618,8 +631,11 @@ def tar_task_definition(self, name: str, contents: str) -> bytes:
618
631
619
632
return tarstream .getvalue ()
620
633
621
- def start_container (self , image : Image , container_name : str , repo_path : Path ) -> Container :
634
+ def start_container (self , image , container_name : str , repo_path : Path ):
622
635
""" Starts a container with the image and name ``container_name`` and copies the repository into the container.
636
+
637
+ :type image: docker.models.images.Image
638
+ :rtype: docker.models.container.Container
623
639
"""
624
640
container = self .client .containers .run (image , command = "bash -i" , detach = True , tty = True , name = container_name ,
625
641
working_dir = str ((Path ("/srv/data" ) / self .cwd ).resolve ()),
@@ -631,7 +647,7 @@ def start_container(self, image: Image, container_name: str, repo_path: Path) ->
631
647
632
648
return container
633
649
634
- def get_image_for_repo (self , repo : str , branch : str , git_repo : Repo , repo_path : Path ) -> Image :
650
+ def get_image_for_repo (self , repo : str , branch : str , git_repo : Repo , repo_path : Path ):
635
651
"""
636
652
Returns an image for the specific repo (based on settings and requirements).
637
653
@@ -641,6 +657,8 @@ def get_image_for_repo(self, repo: str, branch: str, git_repo: Repo, repo_path:
641
657
4. Pushes the image to registry so the image is available next time (if ``registry_pull_only`` is not set)
642
658
643
659
See :meth:`run` for parameters descriptions.
660
+
661
+ :rtype: docker.models.images.Image
644
662
"""
645
663
requirements_file = self .get_requirements_file (repo_path )
646
664
dependencies = self .get_dependencies ()
@@ -703,7 +721,7 @@ def run(self, repo: str, branch: str, task: Task, git_repo: Repo, repo_path: Pat
703
721
704
722
container .put_archive ("/srv/scripts" , self .tar_task_definition (task_filename , task_json ))
705
723
706
- res : Optional [ ExecResult ] = None
724
+ res = None
707
725
708
726
try :
709
727
res = container .exec_run (["python" ,
0 commit comments