mirror of
https://github.com/containers/podman-compose.git
synced 2025-03-10 13:08:13 +01:00
#24: basic implementation of "compose run"
This commit is contained in:
parent
eb72a71e9e
commit
2cf7cbba2e
@ -15,6 +15,7 @@ import subprocess
|
|||||||
import time
|
import time
|
||||||
import re
|
import re
|
||||||
import hashlib
|
import hashlib
|
||||||
|
import random
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from shlex import quote as cmd_quote
|
from shlex import quote as cmd_quote
|
||||||
@ -394,16 +395,18 @@ def mount_desc_to_args(compose, mount_desc, srv_name, cnt_name):
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
def container_to_args(compose, cnt):
|
def container_to_args(compose, cnt, detached=True):
|
||||||
dirname = compose.dirname
|
dirname = compose.dirname
|
||||||
shared_vols = compose.shared_vols
|
shared_vols = compose.shared_vols
|
||||||
pod = cnt.get('pod') or ''
|
pod = cnt.get('pod') or ''
|
||||||
podman_args = [
|
podman_args = [
|
||||||
'run',
|
'run',
|
||||||
'--name={}'.format(cnt.get('name')),
|
'--name={}'.format(cnt.get('name')),
|
||||||
'-d'
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
if detached:
|
||||||
|
podman_args.append("-d")
|
||||||
|
|
||||||
if pod:
|
if pod:
|
||||||
podman_args.append('--pod={}'.format(pod))
|
podman_args.append('--pod={}'.format(pod))
|
||||||
sec = norm_as_list(cnt.get("security_opt"))
|
sec = norm_as_list(cnt.get("security_opt"))
|
||||||
@ -578,6 +581,7 @@ class PodmanCompose:
|
|||||||
self.containers = None
|
self.containers = None
|
||||||
self.shared_vols = None
|
self.shared_vols = None
|
||||||
self.container_names_by_service = None
|
self.container_names_by_service = None
|
||||||
|
self.container_by_name = None
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
args = self._parse_args()
|
args = self._parse_args()
|
||||||
@ -618,7 +622,7 @@ class PodmanCompose:
|
|||||||
dirname = os.path.dirname(filename)
|
dirname = os.path.dirname(filename)
|
||||||
dir_basename = os.path.basename(dirname)
|
dir_basename = os.path.basename(dirname)
|
||||||
self.dirname = dirname
|
self.dirname = dirname
|
||||||
|
os.chdir(dirname)
|
||||||
|
|
||||||
if not project_name:
|
if not project_name:
|
||||||
project_name = dir_basename
|
project_name = dir_basename
|
||||||
@ -702,6 +706,7 @@ class PodmanCompose:
|
|||||||
project_name, container_names_by_service, given_containers)
|
project_name, container_names_by_service, given_containers)
|
||||||
self.pods = pods
|
self.pods = pods
|
||||||
self.containers = containers
|
self.containers = containers
|
||||||
|
self.container_by_name = dict([ (c["name"], c) for c in containers])
|
||||||
|
|
||||||
|
|
||||||
def _parse_args(self):
|
def _parse_args(self):
|
||||||
@ -714,6 +719,7 @@ class PodmanCompose:
|
|||||||
|
|
||||||
def _init_cmd_parser(self, global_args):
|
def _init_cmd_parser(self, global_args):
|
||||||
cmd_name = global_args.command
|
cmd_name = global_args.command
|
||||||
|
# TODO: use parser.add_subparsers
|
||||||
parser = argparse.ArgumentParser(description=self.commands[cmd_name]._cmd_desc)
|
parser = argparse.ArgumentParser(description=self.commands[cmd_name]._cmd_desc)
|
||||||
parser.prog+=' '+cmd_name
|
parser.prog+=' '+cmd_name
|
||||||
# self._init_global_parser(parser)
|
# self._init_global_parser(parser)
|
||||||
@ -824,17 +830,7 @@ def compose_build(compose, args):
|
|||||||
build_args.append(ctx)
|
build_args.append(ctx)
|
||||||
compose.podman.run(build_args, sleep=0)
|
compose.podman.run(build_args, sleep=0)
|
||||||
|
|
||||||
@cmd_run(podman_compose, 'up', 'Create and start the entire stack or some of its services')
|
def create_pods(compose, args):
|
||||||
def compose_up(compose, args):
|
|
||||||
shared_vols = compose.shared_vols
|
|
||||||
os.chdir(compose.dirname)
|
|
||||||
# NOTE: podman does not cache, so don't always build
|
|
||||||
# TODO: if build and the following command fails "podman inspect -t image <image_name>" then run build
|
|
||||||
|
|
||||||
# no need remove them if they have same hash label
|
|
||||||
if compose.global_args.no_cleanup == False:
|
|
||||||
compose.commands['down'](compose, args)
|
|
||||||
|
|
||||||
for pod in compose.pods:
|
for pod in compose.pods:
|
||||||
podman_args = [
|
podman_args = [
|
||||||
"pod", "create",
|
"pod", "create",
|
||||||
@ -846,6 +842,19 @@ def compose_up(compose, args):
|
|||||||
podman_args.extend(['-p', i])
|
podman_args.extend(['-p', i])
|
||||||
compose.podman.run(podman_args)
|
compose.podman.run(podman_args)
|
||||||
|
|
||||||
|
@cmd_run(podman_compose, 'up', 'Create and start the entire stack or some of its services')
|
||||||
|
def compose_up(compose, args):
|
||||||
|
shared_vols = compose.shared_vols
|
||||||
|
|
||||||
|
# NOTE: podman does not cache, so don't always build
|
||||||
|
# TODO: if build and the following command fails "podman inspect -t image <image_name>" then run build
|
||||||
|
|
||||||
|
# no need remove them if they have same hash label
|
||||||
|
if compose.global_args.no_cleanup == False:
|
||||||
|
compose.commands['down'](compose, args)
|
||||||
|
|
||||||
|
create_pods(compose, args)
|
||||||
|
|
||||||
for cnt in compose.containers:
|
for cnt in compose.containers:
|
||||||
# TODO: -e , --add-host, -v, --read-only
|
# TODO: -e , --add-host, -v, --read-only
|
||||||
podman_args = container_to_args(compose, cnt)
|
podman_args = container_to_args(compose, cnt)
|
||||||
@ -861,6 +870,40 @@ def compose_down(compose, args):
|
|||||||
for pod in compose.pods:
|
for pod in compose.pods:
|
||||||
compose.podman.run(["pod", "rm", pod["name"]], sleep=0)
|
compose.podman.run(["pod", "rm", pod["name"]], sleep=0)
|
||||||
|
|
||||||
|
@cmd_run(podman_compose, 'run', 'create a container similar to a service to run a one-off command')
|
||||||
|
def compose_run(compose, args):
|
||||||
|
create_pods(compose, args)
|
||||||
|
print(args)
|
||||||
|
container_names=compose.container_names_by_service[args.service]
|
||||||
|
container_name=container_names[0]
|
||||||
|
cnt = compose.container_by_name[container_name]
|
||||||
|
deps = cnt["_deps"]
|
||||||
|
if not args.no_deps:
|
||||||
|
# TODO: start services in deps
|
||||||
|
pass
|
||||||
|
# adjust one-off container options
|
||||||
|
name0 = "{}_{}_tmp{}".format(compose.project_name, args.service, random.randrange(0, 65536))
|
||||||
|
cnt["name"] = args.name or name0
|
||||||
|
if args.entrypoint: cnt["entrypoint"] = args.entrypoint
|
||||||
|
if args.user: cnt["user"] = args.user
|
||||||
|
if args.workdir: cnt["working_dir"] = args.workdir
|
||||||
|
if not args.service_ports:
|
||||||
|
for k in ("expose", "publishall", "ports"):
|
||||||
|
try: del cnt[k]
|
||||||
|
except KeyError: pass
|
||||||
|
if args.volume:
|
||||||
|
# TODO: handle volumes
|
||||||
|
pass
|
||||||
|
cnt['tty']=False if args.T else True
|
||||||
|
cnt['command']=args.command
|
||||||
|
# run podman
|
||||||
|
podman_args = container_to_args(compose, cnt, args.detach)
|
||||||
|
if not args.detach:
|
||||||
|
podman_args.insert(1, '-i')
|
||||||
|
if args.rm:
|
||||||
|
podman_args.insert(1, '--rm')
|
||||||
|
compose.podman.run(podman_args, sleep=0)
|
||||||
|
|
||||||
|
|
||||||
def transfer_service_status(compose, args, action):
|
def transfer_service_status(compose, args, action):
|
||||||
# TODO: handle dependencies, handle creations
|
# TODO: handle dependencies, handle creations
|
||||||
@ -893,14 +936,47 @@ def compose_restart(compose, args):
|
|||||||
# command arguments parsing
|
# command arguments parsing
|
||||||
###################
|
###################
|
||||||
|
|
||||||
|
@cmd_parse(podman_compose, 'run')
|
||||||
|
def compose_run_parse(parser):
|
||||||
|
parser.add_argument("-d", "--detach", action='store_true',
|
||||||
|
help="Detached mode: Run container in the background, print new container name.")
|
||||||
|
parser.add_argument("--name", type=str, default=None,
|
||||||
|
help="Assign a name to the container")
|
||||||
|
parser.add_argument("--entrypoint", type=str, default=None,
|
||||||
|
help="Override the entrypoint of the image.")
|
||||||
|
parser.add_argument('-e', metavar="KEY=VAL", action='append',
|
||||||
|
help="Set an environment variable (can be used multiple times)")
|
||||||
|
parser.add_argument('-l', '--label', metavar="KEY=VAL", action='append',
|
||||||
|
help="Add or override a label (can be used multiple times)")
|
||||||
|
parser.add_argument("-u", "--user", type=str, default=None,
|
||||||
|
help="Run as specified username or uid")
|
||||||
|
parser.add_argument("--no-deps", action='store_true',
|
||||||
|
help="Don't start linked services")
|
||||||
|
parser.add_argument("--rm", action='store_true',
|
||||||
|
help="Remove container after run. Ignored in detached mode.")
|
||||||
|
parser.add_argument('-p', '--publish', action='append',
|
||||||
|
help="Publish a container's port(s) to the host (can be used multiple times)")
|
||||||
|
parser.add_argument("--service-ports", action='store_true',
|
||||||
|
help="Run command with the service's ports enabled and mapped to the host.")
|
||||||
|
parser.add_argument('-v', '--volume', action='append',
|
||||||
|
help="Bind mount a volume (can be used multiple times)")
|
||||||
|
parser.add_argument("-T", action='store_true',
|
||||||
|
help="Disable pseudo-tty allocation. By default `podman-compose run` allocates a TTY.")
|
||||||
|
parser.add_argument("-w", "--workdir", type=str, default=None,
|
||||||
|
help="Working directory inside the container")
|
||||||
|
parser.add_argument('service', metavar='service', nargs=None,
|
||||||
|
help='service name')
|
||||||
|
parser.add_argument('command', metavar='command', nargs=argparse.REMAINDER,
|
||||||
|
help='comman and its args')
|
||||||
|
|
||||||
@cmd_parse(podman_compose, ['stop', 'restart'])
|
@cmd_parse(podman_compose, ['stop', 'restart'])
|
||||||
def compose_stop_restart_parse(parser):
|
def compose_parse_timeout(parser):
|
||||||
parser.add_argument("-t", "--timeout",
|
parser.add_argument("-t", "--timeout",
|
||||||
help="Specify a shutdown timeout in seconds. ",
|
help="Specify a shutdown timeout in seconds. ",
|
||||||
type=float, default=10)
|
type=float, default=10)
|
||||||
|
|
||||||
@cmd_parse(podman_compose, ['start', 'stop', 'restart'])
|
@cmd_parse(podman_compose, ['start', 'stop', 'restart'])
|
||||||
def compose_statu_parse(parser):
|
def compose_parse_services(parser):
|
||||||
parser.add_argument('services', metavar='services', nargs='+',
|
parser.add_argument('services', metavar='services', nargs='+',
|
||||||
help='affected services')
|
help='affected services')
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user