init commit
This commit is contained in:
commit
460f6893e6
15
base-img/alt.yaml
Normal file
15
base-img/alt.yaml
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
FROM scratch
|
||||||
|
|
||||||
|
MAINTAINER \
|
||||||
|
[Alexey Shabalin <shaba@altlinux.org>] \
|
||||||
|
[Nadezhda Fedorova <fedor@altlinux.org]
|
||||||
|
|
||||||
|
LABEL org.opencontainers.image.licenses="{{lic}}"
|
||||||
|
LABEL org.opencontainers.image.vendor="ALT Linux Team"
|
||||||
|
|
||||||
|
ADD {{source}} /
|
||||||
|
|
||||||
|
RUN true > /etc/security/limits.d/50-defaults.conf
|
||||||
|
|
||||||
|
# overwrite this with 'CMD []' in a dependent Dockerfile
|
||||||
|
CMD ["/bin/bash"]
|
279
build.py
Executable file
279
build.py
Executable file
@ -0,0 +1,279 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
from pathlib import Path
|
||||||
|
import urllib.request
|
||||||
|
import shutil
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
from jinja2 import Template
|
||||||
|
import json
|
||||||
|
|
||||||
|
LIC_C="ALT-SP-Container"
|
||||||
|
LIC_P="ALT-Container or GPLv3"
|
||||||
|
LIC_SIS="GPLv3"
|
||||||
|
|
||||||
|
builddir= "./"
|
||||||
|
dockerfile = "Dockerfile"
|
||||||
|
|
||||||
|
arch_map= {'amd64': "x86_64", '386': "i586", 'arm64': "aarch64", "riscv64": "riscv64", "loongarch64": "loongarch64" }
|
||||||
|
|
||||||
|
def parse_args():
|
||||||
|
registry = "gitea.basealt.ru"
|
||||||
|
arches = ["amd64", "386", "arm64", "loongarch64", "riscv64"]
|
||||||
|
names=["alt"]
|
||||||
|
latest_tag="p10"
|
||||||
|
org="alt"
|
||||||
|
branches=["p11", "p10", "Sisyphus"]
|
||||||
|
exclusions='{"p10": ["loongarch64", "riscv64"], "p11": ["loongarch64", "riscv64"]}'
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-b",
|
||||||
|
"--branches",
|
||||||
|
nargs="+",
|
||||||
|
default=branches,
|
||||||
|
choices=branches,
|
||||||
|
help="list of branches",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-e",
|
||||||
|
"--exclusions",
|
||||||
|
default=exclusions,
|
||||||
|
choices=exclusions,
|
||||||
|
type=json.loads,
|
||||||
|
help="list of branches with exclusion arches which no need built",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-n",
|
||||||
|
"--names",
|
||||||
|
nargs="+",
|
||||||
|
default=names,
|
||||||
|
choices=names,
|
||||||
|
help="list of names images in templates directory",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-a",
|
||||||
|
"--arches",
|
||||||
|
nargs="+",
|
||||||
|
default=arches,
|
||||||
|
choices=arches,
|
||||||
|
help="build images for these architectures",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-r",
|
||||||
|
"--registry",
|
||||||
|
default=registry,
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--org",
|
||||||
|
default=org,
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--no-push",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--use-local-source",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-l",
|
||||||
|
"--latest",
|
||||||
|
default=latest_tag,
|
||||||
|
help="tag images in this branch as latest",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--old-structure",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--new-structure",
|
||||||
|
)
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
return args
|
||||||
|
|
||||||
|
def run(args):
|
||||||
|
result = subprocess.run(
|
||||||
|
args,
|
||||||
|
capture_output = True,
|
||||||
|
text = True
|
||||||
|
)
|
||||||
|
if result.stderr is not None:
|
||||||
|
print(result.stderr)
|
||||||
|
return False
|
||||||
|
print(result.stdout)
|
||||||
|
return True
|
||||||
|
|
||||||
|
def render_templ(path, lic, source):
|
||||||
|
templatepath = Path(path)
|
||||||
|
if templatepath.exists():
|
||||||
|
template = templatepath.read_text()
|
||||||
|
rendered = Template(template).render(
|
||||||
|
source=source,
|
||||||
|
lic=lic,
|
||||||
|
)
|
||||||
|
Path(f'{builddir}{dockerfile}').write_text(rendered + "\n")
|
||||||
|
|
||||||
|
def create_dir(name):
|
||||||
|
try:
|
||||||
|
path = Path(name)
|
||||||
|
path.mkdir(parents=True, exist_ok=True)
|
||||||
|
print(f"Directory '{name}' created successfully.")
|
||||||
|
except FileExistsError:
|
||||||
|
print(f"Directory '{name}' already exists.")
|
||||||
|
except PermissionError:
|
||||||
|
print(f"Permission denied: Unable to create '{name}'.")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"An error occurred: {e}")
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
args = parse_args()
|
||||||
|
|
||||||
|
#temp dir to dowdload images from ftp or copy locals
|
||||||
|
tempdir = Path.home().joinpath(".local/share/images")
|
||||||
|
create_dir(tempdir)
|
||||||
|
#directory with templates of base inages
|
||||||
|
walkdir = Path("./base-img")
|
||||||
|
print(f'walk path = {walkdir.as_posix()}')
|
||||||
|
|
||||||
|
#go walk throw directory with templates
|
||||||
|
for img in walkdir.rglob('*'):
|
||||||
|
#get template file name
|
||||||
|
imgname = img.name.replace(".yaml", "")
|
||||||
|
#if img is file and its file name in templates input list
|
||||||
|
if img.is_file() and imgname in args.names:
|
||||||
|
print(f'start building image {img.name}')
|
||||||
|
|
||||||
|
for br in args.branches:
|
||||||
|
#set license string for containers label
|
||||||
|
print(f'branch {br}')
|
||||||
|
LIC=LIC_SIS
|
||||||
|
if "p1" in br:
|
||||||
|
LIC=LIC_P
|
||||||
|
elif "c" in br:
|
||||||
|
LIC=LIC_C
|
||||||
|
|
||||||
|
tag = br.lower()
|
||||||
|
#new_tag = datetime.now().strftime("%Y%m%d")
|
||||||
|
manifest = f'{args.registry}/{args.org}/{imgname}'
|
||||||
|
#new_manifest = f"args.registry/{br}/{imgname}"
|
||||||
|
|
||||||
|
excl_arches = []
|
||||||
|
if args.exclusions is not None and args.exclusions.get(br) is not None:
|
||||||
|
excl_arches = args.exclusions.get(br)
|
||||||
|
|
||||||
|
for a in args.arches:
|
||||||
|
if a in excl_arches:
|
||||||
|
continue
|
||||||
|
|
||||||
|
print(f'arch {a}')
|
||||||
|
|
||||||
|
file_arch = arch_map.get(a)
|
||||||
|
if file_arch is None:
|
||||||
|
print(f'not found arch name {a} for file in map {arch_map}')
|
||||||
|
continue
|
||||||
|
|
||||||
|
source = f"alt-{tag}-rootfs-minimal-{file_arch}.tar.xz"
|
||||||
|
|
||||||
|
if args.use_local_source:
|
||||||
|
print('use local source mode')
|
||||||
|
#version for cloud image forge with getting source from local filesystem
|
||||||
|
source_path=f"/home/builder/proto/{br}/cloud/{file_arch}"
|
||||||
|
shutil.copy2(source_path + "/" + source, builddir)
|
||||||
|
else:
|
||||||
|
print('use download mode from ftp')
|
||||||
|
sourceurl = f"http://ftp.altlinux.org/pub/distributions/ALTLinux/images/{br}/cloud/{file_arch}/{source}"
|
||||||
|
print(f"source url {sourceurl}")
|
||||||
|
download_path = f'{tempdir.as_posix()}/{source}'
|
||||||
|
print(f"downland path {download_path}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
urllib.request.urlretrieve(sourceurl, download_path)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"download error: {e}")
|
||||||
|
print(f"skip building {img.name} for {br} and {a}")
|
||||||
|
continue
|
||||||
|
|
||||||
|
print(f'file is downloaded to {download_path}')
|
||||||
|
run(["cp",
|
||||||
|
download_path,
|
||||||
|
builddir,
|
||||||
|
])
|
||||||
|
|
||||||
|
#delete downlouded from ftp image source
|
||||||
|
tempdir.joinpath(source).unlink()
|
||||||
|
|
||||||
|
#"--build-arg SOURCE=" + source,
|
||||||
|
#"--build-arg LICENSE=" + LIC,
|
||||||
|
print(f'render file {img.as_posix()}, set license {LIC} and source {source}')
|
||||||
|
render_templ(img.as_posix(), LIC, source)
|
||||||
|
print(f'template {img.name} is rendered to Dockerfile')
|
||||||
|
|
||||||
|
#build manifest
|
||||||
|
run(["podman",
|
||||||
|
"build",
|
||||||
|
f"--manifest={manifest}:{tag}",
|
||||||
|
f"--platform=linux/{a}",
|
||||||
|
".",
|
||||||
|
])
|
||||||
|
print(f'manifest {manifest}:{tag} for linux/{a} is builded')
|
||||||
|
|
||||||
|
#delete image source
|
||||||
|
p = Path(f'{builddir}{source}')
|
||||||
|
if p.exists():
|
||||||
|
p.unlink()
|
||||||
|
#delete dockerfile
|
||||||
|
p = Path(f'{builddir}{dockerfile}')
|
||||||
|
if p.exists():
|
||||||
|
p.unlink()
|
||||||
|
|
||||||
|
if args.no_push:
|
||||||
|
print('no push mode')
|
||||||
|
continue
|
||||||
|
|
||||||
|
print(f'push manifest to registry {args.registry}')
|
||||||
|
|
||||||
|
run(["podman",
|
||||||
|
"manifest",
|
||||||
|
"push",
|
||||||
|
"--all",
|
||||||
|
f"{manifest}:{tag}",
|
||||||
|
f"docker://{manifest}:{tag}",
|
||||||
|
])
|
||||||
|
|
||||||
|
print(f'manifest {manifest}:{tag} is pushed to registry {args.registry}')
|
||||||
|
|
||||||
|
if args.latest == br:
|
||||||
|
print(f"push latest tag")
|
||||||
|
run(["podman",
|
||||||
|
"manifest",
|
||||||
|
"push",
|
||||||
|
"--all",
|
||||||
|
f"{manifest}:{tag}",
|
||||||
|
f"docker://{manifest}:latest",
|
||||||
|
])
|
||||||
|
|
||||||
|
run(["podman",
|
||||||
|
"manifest",
|
||||||
|
"rm",
|
||||||
|
f"{manifest}:latest",
|
||||||
|
])
|
||||||
|
|
||||||
|
run(["podman",
|
||||||
|
"manifest",
|
||||||
|
"rm",
|
||||||
|
f"{manifest}:{tag}",
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user