add docker-compose parser
parent
6a9fde111a
commit
d713e51ec0
|
|
@ -0,0 +1,6 @@
|
||||||
|
[submodule "sample/bitpoll"]
|
||||||
|
path = sample/bitpoll
|
||||||
|
url = ssh://git@git.wiai.de:22222/server/bitpoll.git
|
||||||
|
[submodule "sample/bitpoll_0.1"]
|
||||||
|
path = sample/bitpoll_0.1
|
||||||
|
url = ssh://git@git.wiai.de:22222/server/bitpoll.git
|
||||||
|
|
@ -0,0 +1,120 @@
|
||||||
|
import argparse
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
import logging
|
||||||
|
|
||||||
|
import yaml
|
||||||
|
|
||||||
|
from collections import namedtuple
|
||||||
|
|
||||||
|
log = logging # TODO: config
|
||||||
|
|
||||||
|
COMPOSE_FILE = "docker-compose.yml"
|
||||||
|
DOCKERFILE = "Dockerfile"
|
||||||
|
|
||||||
|
Image = namedtuple("Image", ["image", "tag"])
|
||||||
|
Service = namedtuple("Service", ["path", "name"])
|
||||||
|
|
||||||
|
UNTAGGED = Image(image="unnamed", tag="untagged")
|
||||||
|
|
||||||
|
def load_compose_config(f):
|
||||||
|
config = subprocess.check_output(["docker-compose", "-f", f, "config"])
|
||||||
|
#print(config.decode("utf8"))
|
||||||
|
struct = yaml.load(config)
|
||||||
|
#json.dump(struct, open(f"{f}.json", "w"), indent=1)
|
||||||
|
#print(struct)
|
||||||
|
return struct
|
||||||
|
|
||||||
|
def source_to_image(source):
|
||||||
|
return source.strip().split(" ")[1]
|
||||||
|
|
||||||
|
def parse_dockerfile(f):
|
||||||
|
if not f.endswith(DOCKERFILE):
|
||||||
|
log.warn(f"guessing Döckerfile… {f}")
|
||||||
|
f = os.path.join(f, DOCKERFILE)
|
||||||
|
keyword = "FROM"
|
||||||
|
with open(f, "r") as src:
|
||||||
|
sources = [source_to_image(line) for line in src if line.strip().startswith(keyword)]
|
||||||
|
return sources
|
||||||
|
|
||||||
|
def image_info(image):
|
||||||
|
image, tag = image.strip().split(":")
|
||||||
|
return Image(image=image, tag=tag)
|
||||||
|
|
||||||
|
class Collector:
|
||||||
|
def __init__(self):
|
||||||
|
self.store = {}
|
||||||
|
|
||||||
|
def add(self, config, path):
|
||||||
|
self.store[path] = config
|
||||||
|
|
||||||
|
def get_images(self):
|
||||||
|
images = []
|
||||||
|
for path, config in self.store.items():
|
||||||
|
if not "services" in config:
|
||||||
|
log.error(f"no services defined in {path}")
|
||||||
|
continue
|
||||||
|
images += [service["image"] for name,service in config["services"].items() if "image" in service]
|
||||||
|
return images
|
||||||
|
|
||||||
|
def get_services_info(self):
|
||||||
|
images = {}
|
||||||
|
for path, config in self.store.items():
|
||||||
|
services = {}
|
||||||
|
if not "services" in config:
|
||||||
|
log.error(f"no services defined in {path}")
|
||||||
|
continue
|
||||||
|
for name, service in config["services"].items():
|
||||||
|
services[name] = {}
|
||||||
|
for k in ["image", "build"]:
|
||||||
|
if k in service:
|
||||||
|
services[name][k] = service[k]
|
||||||
|
images[path] = services
|
||||||
|
return images
|
||||||
|
|
||||||
|
def get_images_sources(self):
|
||||||
|
services = self.get_services_info()
|
||||||
|
images = {}
|
||||||
|
for path, services in services.items():
|
||||||
|
for name, service in services.items():
|
||||||
|
service_info = {
|
||||||
|
"path": path,
|
||||||
|
"service_name": name
|
||||||
|
}
|
||||||
|
image = UNTAGGED
|
||||||
|
if "build" in service:
|
||||||
|
service_info["base_images"] = parse_dockerfile(service["build"]["context"])
|
||||||
|
if "image" in service:
|
||||||
|
image = image_info(service["image"])
|
||||||
|
if not image.image in images:
|
||||||
|
images[image.image] = {}
|
||||||
|
if not image.tag in images[image.image]:
|
||||||
|
images[image.image][image.tag] = [service_info]
|
||||||
|
else:
|
||||||
|
images[image.image][image.tag] += [service_info]
|
||||||
|
return images
|
||||||
|
|
||||||
|
def start(files):
|
||||||
|
collector = Collector()
|
||||||
|
for f in files:
|
||||||
|
if not f.endswith(COMPOSE_FILE):
|
||||||
|
log.warn(f"guessing docker-compöse.yml… {f}")
|
||||||
|
f = os.path.join(f, COMPOSE_FILE)
|
||||||
|
if not os.path.exists(f):
|
||||||
|
log.error(f"file {f} does not exist")
|
||||||
|
continue
|
||||||
|
config = load_compose_config(f)
|
||||||
|
collector.add(config, f)
|
||||||
|
#print(json.dumps(collector.get_services_info(), indent=1))
|
||||||
|
print(json.dumps(collector.get_images_sources(), indent=1))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
parser = argparse.ArgumentParser(description="Docker-compose parser")
|
||||||
|
parser.add_argument("compose_files", nargs="+")
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
start(args.compose_files)
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit c178a79530b409733c26f13b851a8b65b20a40b4
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit a3c90ba0ce2539a3a9e4ce46a2c0431ebb02f02f
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
version: "2"
|
||||||
|
|
||||||
|
services:
|
||||||
|
http:
|
||||||
|
image: httpd:alpine
|
||||||
|
# ports:
|
||||||
|
# - "80:80"
|
||||||
|
volumes:
|
||||||
|
- /home/clemens/public_html/:/usr/local/apache2/htdocs/
|
||||||
|
networks:
|
||||||
|
- traefik_net
|
||||||
|
labels:
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.docker.network=traefik_net"
|
||||||
|
- "traefik.http.frontend.rule=Host:potato.kinf.wiai.uni-bamberg.de,www.potato.kinf.wiai.uni-bamberg.de,141.13.94.68,localhost,uni.clkl.de"
|
||||||
|
networks:
|
||||||
|
traefik_net:
|
||||||
|
external:
|
||||||
|
name: traefik_net
|
||||||
Loading…
Reference in New Issue