-
Notifications
You must be signed in to change notification settings - Fork 42
/
local_image_build.py
128 lines (110 loc) · 4.44 KB
/
local_image_build.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# (c) 2012-2020, Ansible by Red Hat
#
# This file is part of Ansible Galaxy
#
# Ansible Galaxy is free software: you can redistribute it and/or modify
# it under the terms of the Apache License as published by
# the Apache Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# Ansible Galaxy is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# Apache License for more details.
#
# You should have received a copy of the Apache License
# along with Galaxy. If not, see <http://www.apache.org/licenses/>.
import logging
import os
import pkg_resources
import shutil
import tempfile
from galaxy_importer import exceptions
from shutil import copy
from subprocess import Popen, PIPE, STDOUT, run, CalledProcessError
default_logger = logging.getLogger(__name__)
class Build(object):
"""Use docker/podman to build ansible-test image with artifact inside."""
def __init__(self, filepath, collection_name, cfg, logger=default_logger):
self.cfg = cfg
self.container_engine = Build.get_container_engine(cfg)
self.filepath = filepath
self.log = logger or default_logger
self.image = ""
self.working_dir = tempfile.TemporaryDirectory()
def build_image(self):
if self.container_engine == "docker":
self.log.info("Building Dockerfile")
else:
self.log.info("Building ContainerFile")
Build._build_dockerfile(self.working_dir.name)
Build._copy_collection_file(dir=self.working_dir.name, filepath=self.filepath)
self.log.info("Building image...")
self.image = Build._build_image_with_artifact(
container_engine=self.container_engine, dir=self.working_dir.name
)
return self.image
def cleanup(self):
self.log.info("Removing temporary files, image and container")
self.working_dir.cleanup()
cmd = [self.container_engine, "image", "rm", "-f", self.image]
try:
run(cmd)
except CalledProcessError as e:
raise exceptions.AnsibleTestError(
"An exception occurred in: {}, message={}".format(" ".join(cmd), e.msg)
)
@staticmethod
def get_container_engine(cfg):
if cfg.local_image_docker is True:
return "docker"
else:
return "podman"
def _build_dockerfile(dir):
pkg_dockerfile = pkg_resources.resource_filename(
"galaxy_importer", "ansible_test/container/Dockerfile"
)
file_location = os.path.join(dir, "Dockerfile")
shutil.copyfile(pkg_dockerfile, file_location)
with open(file_location, "r+") as f:
lines = f.readlines()
for index, line in enumerate(lines):
if "ENV HOME" in line:
# TODO move RUN command to base image
lines.insert(index - 1, "\nRUN chown -R user1:root /archive\n")
lines.insert(index - 1, "\nCOPY archive.tar.gz /archive/archive.tar.gz\n")
break
f.seek(0)
f.writelines(lines)
def _build_image_with_artifact(container_engine, dir):
pkg_entrypoint = pkg_resources.resource_filename(
"galaxy_importer", "ansible_test/container/entrypoint.sh"
)
eda_linting = pkg_resources.resource_filename(
"galaxy_importer", "ansible_test/container/eda/tox.ini"
)
shutil.copyfile(pkg_entrypoint, os.path.join(dir, "entrypoint.sh"))
os.mkdir(os.path.join(dir, "eda"))
shutil.copyfile(eda_linting, os.path.join(dir, "eda", "tox.ini"))
cmd = [container_engine, "build", ".", "--quiet"]
proc = Popen(
cmd,
cwd=dir,
stdout=PIPE,
stderr=STDOUT,
encoding="utf-8",
)
image_id = ""
for line in proc.stdout:
image_id = line.strip()
return_code = proc.wait()
if return_code != 0:
raise exceptions.AnsibleTestError(
"An exception occurred in {}, returncode={}".format(" ".join(cmd), return_code)
)
if container_engine == "docker":
image_id = image_id.split(":")[-1]
return image_id
def _copy_collection_file(dir, filepath):
path = os.path.join(dir, "archive.tar.gz")
copy(filepath, path)