convert to podman
* call podman exec instead of using API: - build does not support progress - run looks like to lack equivalent dockerpty support * config: use full uri as short names are not supported on all OSes (like debian 11)
This commit is contained in:
parent
bd6a026e9c
commit
e0b228799f
@ -21,9 +21,6 @@ debian_base: &debian_base
|
|||||||
binds:
|
binds:
|
||||||
- /etc/timezone:ro
|
- /etc/timezone:ro
|
||||||
- /etc/localtime:ro
|
- /etc/localtime:ro
|
||||||
- /etc/passwd:ro
|
|
||||||
- /etc/group:ro
|
|
||||||
- /etc/shadow:ro
|
|
||||||
- "{home}"
|
- "{home}"
|
||||||
environment:
|
environment:
|
||||||
- USER
|
- USER
|
||||||
@ -33,7 +30,7 @@ debian_base: &debian_base
|
|||||||
|
|
||||||
debian9:
|
debian9:
|
||||||
<<: *debian_base
|
<<: *debian_base
|
||||||
image: debian:9
|
image: docker.io/debian:9
|
||||||
dockerfile:
|
dockerfile:
|
||||||
- ARG DEBIAN_FRONTEND=noninteractive
|
- ARG DEBIAN_FRONTEND=noninteractive
|
||||||
- RUN echo "deb http://archive.debian.org/debian stretch main" > /etc/apt/sources.list
|
- RUN echo "deb http://archive.debian.org/debian stretch main" > /etc/apt/sources.list
|
||||||
@ -46,23 +43,24 @@ debian9:
|
|||||||
|
|
||||||
debian10:
|
debian10:
|
||||||
<<: *debian_base
|
<<: *debian_base
|
||||||
image: debian:10
|
image: docker.io/debian:10
|
||||||
|
|
||||||
debian11:
|
debian11:
|
||||||
<<: *debian_base
|
<<: *debian_base
|
||||||
image: debian:11
|
image: docker.io/debian:11
|
||||||
|
|
||||||
debian12:
|
debian12:
|
||||||
<<: *debian_base
|
<<: *debian_base
|
||||||
image: debian:12
|
image: docker.io/debian:12
|
||||||
|
|
||||||
ubuntu20.04:
|
ubuntu20.04:
|
||||||
<<: *debian_base
|
<<: *debian_base
|
||||||
image: ubuntu:20.04
|
image: docker.io/ubuntu:20.04
|
||||||
|
|
||||||
ubuntu22.04:
|
ubuntu22.04:
|
||||||
<<: *debian_base
|
<<: *debian_base
|
||||||
image: ubuntu:22.04
|
image: docker.io/ubuntu:22.04
|
||||||
|
|
||||||
rh_base: &rh_base
|
rh_base: &rh_base
|
||||||
dockerfile:
|
dockerfile:
|
||||||
- RUN dnf install -y sudo
|
- RUN dnf install -y sudo
|
||||||
@ -80,9 +78,6 @@ rh_base: &rh_base
|
|||||||
binds:
|
binds:
|
||||||
- /etc/timezone:ro
|
- /etc/timezone:ro
|
||||||
- /etc/localtime:ro
|
- /etc/localtime:ro
|
||||||
- /etc/passwd:ro
|
|
||||||
- /etc/group:ro
|
|
||||||
- /etc/shadow:ro
|
|
||||||
- "{home}"
|
- "{home}"
|
||||||
environment:
|
environment:
|
||||||
- USER
|
- USER
|
||||||
@ -93,7 +88,7 @@ rh_base: &rh_base
|
|||||||
|
|
||||||
centos7:
|
centos7:
|
||||||
<<: *rh_base
|
<<: *rh_base
|
||||||
image: centos:7
|
image: docker.io/centos:7
|
||||||
dockerfile:
|
dockerfile:
|
||||||
- RUN yum install -y sudo
|
- RUN yum install -y sudo
|
||||||
- RUN echo "Defaults lecture = never" >> /etc/sudoers
|
- RUN echo "Defaults lecture = never" >> /etc/sudoers
|
||||||
@ -104,9 +99,9 @@ centos7:
|
|||||||
|
|
||||||
rocky8:
|
rocky8:
|
||||||
<<: *rh_base
|
<<: *rh_base
|
||||||
image: rockylinux:8
|
image: docker.io/rockylinux:8
|
||||||
|
|
||||||
rocky9:
|
rocky9:
|
||||||
<<: *rh_base
|
<<: *rh_base
|
||||||
image: rockylinux:9
|
image: docker.io/rockylinux:9
|
||||||
|
|
||||||
|
102
runon/runon.py
102
runon/runon.py
@ -1,13 +1,8 @@
|
|||||||
import sys
|
import sys
|
||||||
|
import os
|
||||||
import argparse
|
import argparse
|
||||||
import docker
|
|
||||||
import dockerpty
|
|
||||||
import io
|
|
||||||
import getpass
|
import getpass
|
||||||
import pathlib
|
import pathlib
|
||||||
import platform
|
|
||||||
import os
|
|
||||||
import re
|
|
||||||
import xdg.BaseDirectory
|
import xdg.BaseDirectory
|
||||||
import yaml
|
import yaml
|
||||||
import datetime
|
import datetime
|
||||||
@ -80,16 +75,10 @@ def make_osname_link(binpath, osname):
|
|||||||
except FileExistsError:
|
except FileExistsError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def make_image_name(osname):
|
|
||||||
user = getpass.getuser()
|
|
||||||
name = 'runon-{}-{}'.format(osname, user)
|
|
||||||
return name
|
|
||||||
|
|
||||||
|
def build_image(conf, update, verbose):
|
||||||
def build_image(client, conf, update, verbose):
|
|
||||||
osname = conf.get('osname')
|
osname = conf.get('osname')
|
||||||
image_name = 'runon-{}'.format(osname)
|
image_name = 'runon-{}'.format(osname)
|
||||||
tag = make_image_name(conf['osname'])
|
|
||||||
cache_dir = os.path.join(xdg.BaseDirectory.xdg_cache_home, 'runon')
|
cache_dir = os.path.join(xdg.BaseDirectory.xdg_cache_home, 'runon')
|
||||||
cache_file = os.path.join(cache_dir, image_name)
|
cache_file = os.path.join(cache_dir, image_name)
|
||||||
|
|
||||||
@ -102,28 +91,32 @@ def build_image(client, conf, update, verbose):
|
|||||||
if ts_image and ts_image > ts_conf:
|
if ts_image and ts_image > ts_conf:
|
||||||
if verbose:
|
if verbose:
|
||||||
print('image: {} up-to-date'.format(image_name))
|
print('image: {} up-to-date'.format(image_name))
|
||||||
image = client.images.get(tag)
|
return image_name
|
||||||
return image
|
|
||||||
|
|
||||||
image = conf.get('image')
|
image = conf.get('image')
|
||||||
packages = conf['packages']
|
dockerfile = conf.get('dockerfile')
|
||||||
dockerfile = conf['dockerfile']
|
pkginstall = conf.get('pkginstall')
|
||||||
pkginstall = conf['pkginstall']
|
packages = conf.get('packages')
|
||||||
|
if not dockerfile:
|
||||||
|
dockerfile = []
|
||||||
if image:
|
if image:
|
||||||
dockerfile.insert(0, 'FROM {}'.format(image))
|
dockerfile.insert(0, 'FROM {}'.format(image))
|
||||||
|
if packages:
|
||||||
for p in packages:
|
for p in packages:
|
||||||
dockerfile.append(pkginstall.format(p))
|
dockerfile.append(pkginstall.format(p))
|
||||||
try:
|
|
||||||
if verbose:
|
if verbose:
|
||||||
print('Building image {} ...'.format(tag))
|
print('Dockerfile:')
|
||||||
cmd = ['docker', 'build']
|
for l in dockerfile:
|
||||||
|
print(' * {}'.format(l))
|
||||||
|
print('Building image {} ...'.format(image_name))
|
||||||
|
cmd = ['podman', 'build']
|
||||||
if update:
|
if update:
|
||||||
cmd.append('--no-cache')
|
cmd.append('--no-cache')
|
||||||
cmd += ['-t', tag, '-']
|
cmd += ['-t', image_name, '-']
|
||||||
ret = subprocess.run(cmd,
|
ret = subprocess.run(cmd,
|
||||||
input='\n'.join(dockerfile).encode('utf-8'),
|
input='\n'.join(dockerfile).encode('utf-8'),
|
||||||
stderr=subprocess.STDOUT, check=True)
|
stderr=subprocess.STDOUT, check=True)
|
||||||
image = client.images.get(tag)
|
|
||||||
|
|
||||||
if not os.path.exists(cache_dir):
|
if not os.path.exists(cache_dir):
|
||||||
os.mkdir(cache_dir)
|
os.mkdir(cache_dir)
|
||||||
@ -132,19 +125,14 @@ def build_image(client, conf, update, verbose):
|
|||||||
print('cache: {}'.format(cache_file))
|
print('cache: {}'.format(cache_file))
|
||||||
file.write('')
|
file.write('')
|
||||||
|
|
||||||
except (docker.errors.BuildError, KeyboardInterrupt, subprocess.CalledProcessError, docker.errors.ImageNotFound) as e:
|
return image_name
|
||||||
print('Build Error: {}'.format(e))
|
|
||||||
print()
|
|
||||||
print('with dockerfile:')
|
|
||||||
for line in dockerfile:
|
|
||||||
print(' {}'.format(line))
|
|
||||||
sys.exit(1)
|
|
||||||
return image
|
|
||||||
|
|
||||||
|
|
||||||
def create_container(client, image, conf, command, verbose):
|
def run_image(name, conf, command, verbose):
|
||||||
volumes = {}
|
volumes = {
|
||||||
|
}
|
||||||
environment = {}
|
environment = {}
|
||||||
|
if conf.get('binds'):
|
||||||
for mnt in conf['binds']:
|
for mnt in conf['binds']:
|
||||||
mnt = mnt.split(':')
|
mnt = mnt.split(':')
|
||||||
if mnt[-1] in ['ro','rw']:
|
if mnt[-1] in ['ro','rw']:
|
||||||
@ -155,39 +143,28 @@ def create_container(client, image, conf, command, verbose):
|
|||||||
mnt = mnt[:2]
|
mnt = mnt[:2]
|
||||||
bind = mnt[-1]
|
bind = mnt[-1]
|
||||||
vol = mnt[0]
|
vol = mnt[0]
|
||||||
|
if os.path.exists(vol):
|
||||||
volumes[vol] = { 'bind': bind, 'mode': mode }
|
volumes[vol] = { 'bind': bind, 'mode': mode }
|
||||||
hostname = platform.node()
|
if conf.get('environment'):
|
||||||
for v in conf['environment']:
|
for v in conf['environment']:
|
||||||
e = v.split('=')
|
e = v.split('=')
|
||||||
if len(e) == 1:
|
if len(e) == 1:
|
||||||
e.append(os.getenv(e[0]))
|
e.append(os.getenv(e[0]))
|
||||||
environment[e[0]] = e[1]
|
environment[e[0]] = e[1]
|
||||||
#environment['debian_chroot']=conf['osname']
|
|
||||||
user='{}:{}'.format(os.getuid(), os.getgid())
|
|
||||||
pwd=os.getcwd()
|
|
||||||
|
|
||||||
container = client.containers.create(image, command,
|
cmd = ['podman', 'run', '--rm', '--interactive', '--tty', '--userns=keep-id', '--net=host' ]
|
||||||
detach=False, stdin_open=True, tty=True,
|
for e in environment:
|
||||||
auto_remove=True,
|
cmd += [ '-e', '{}={}'.format(e, environment[e]) ]
|
||||||
hostname=hostname,
|
for v in volumes:
|
||||||
volumes=volumes,
|
cmd += [ '-v', ':'.join([v, volumes[v]['bind'], volumes[v]['mode']]) ]
|
||||||
environment=environment,
|
cmd += [ '--workdir', os.getcwd() ]
|
||||||
user=user,
|
cmd += [ name ]
|
||||||
network_mode='host',
|
if command:
|
||||||
working_dir=pwd
|
cmd += command
|
||||||
)
|
if verbose:
|
||||||
return container
|
print('executing: {}\n'.format(' '.join(cmd)))
|
||||||
|
ret = subprocess.run(cmd)
|
||||||
|
return ret.returncode
|
||||||
def run_container(client, container):
|
|
||||||
try:
|
|
||||||
dockerpty.start(client.api, container.id)
|
|
||||||
container.reload() # to update attrs fields
|
|
||||||
except docker.errors.APIError as e:
|
|
||||||
print('ERROR: {}'.format(e))
|
|
||||||
sys.exit(1)
|
|
||||||
ret = container.attrs['State']['ExitCode']
|
|
||||||
return ret
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
@ -247,10 +224,7 @@ def main():
|
|||||||
make_osname_link(sys.argv[0], args.osname)
|
make_osname_link(sys.argv[0], args.osname)
|
||||||
|
|
||||||
conf = load_config(conf_file, args.osname)
|
conf = load_config(conf_file, args.osname)
|
||||||
|
image_name = build_image(conf, args.update, args.verbose)
|
||||||
client = docker.from_env()
|
ret = run_image(image_name, conf, args.command, args.verbose)
|
||||||
image = build_image(client, conf, args.update, args.verbose)
|
|
||||||
container = create_container(client, image, conf, args.command, args.verbose)
|
|
||||||
ret = run_container(client, container)
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user