diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..f2dd600 --- /dev/null +++ b/.gitmodules @@ -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 diff --git a/docker-compose.py b/docker-compose.py new file mode 100644 index 0000000..6e86059 --- /dev/null +++ b/docker-compose.py @@ -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) \ No newline at end of file diff --git a/sample/bitpoll b/sample/bitpoll new file mode 160000 index 0000000..c178a79 --- /dev/null +++ b/sample/bitpoll @@ -0,0 +1 @@ +Subproject commit c178a79530b409733c26f13b851a8b65b20a40b4 diff --git a/sample/bitpoll_0.1 b/sample/bitpoll_0.1 new file mode 160000 index 0000000..a3c90ba --- /dev/null +++ b/sample/bitpoll_0.1 @@ -0,0 +1 @@ +Subproject commit a3c90ba0ce2539a3a9e4ce46a2c0431ebb02f02f diff --git a/sample/http/docker-compose.yml b/sample/http/docker-compose.yml new file mode 100644 index 0000000..3cbf288 --- /dev/null +++ b/sample/http/docker-compose.yml @@ -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