use packaging.version to compare version and list possible updates for images

master
Clemens Klug 2018-07-24 18:24:48 +02:00
parent 5cef4df383
commit d1872892fd
5 changed files with 101 additions and 26 deletions

View File

@ -6,4 +6,4 @@ services:
volumes:
- ./docker-compose.py:/docker-compose.py
- ./sample:/services
command: bash -c 'python3 /docker-compose.py /services/*'
command: bash -c 'python3 /docker_compose.py /services/*'

View File

@ -109,7 +109,7 @@ class Collector:
def start(files, ignores):
collector = Collector()
for f in files:
if any([i in f for i in ignores]):
if ignores and any([i in f for i in ignores]):
log.warn(f"skip {f} due to ignore rule")
continue
if not f.endswith(COMPOSE_FILE):
@ -124,14 +124,15 @@ def start(files, ignores):
#print(json.dumps(collector.get_images_sources(), indent=1))
return collector.get_images_sources()
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Docker-compose parser")
def args_setup(description):
parser = argparse.ArgumentParser(description=description)
parser.add_argument("compose_files", nargs="+")
parser.add_argument("--output", "-o")
parser.add_argument("--ignore", "-i", nargs="+")
parser.add_argument("--ignore", "-i", nargs="+", default=False)
return parser
if __name__ == "__main__":
parser = args_setup("Docker-compose parser")
args = parser.parse_args()

View File

@ -1,43 +1,80 @@
import requests
from datetime import datetime
import argparse
import json
import logging
from datetime import datetime
from packaging import version
import requests
log = logging
TAGS = "https://registry.hub.docker.com/v2/repositories/{image}/tags/"
LIB_PREFIX = "library/"
TAG_STORE = {}
def get_tags(image):
if "/" not in image:
image = LIB_PREFIX + image
url = TAGS.format(image=image)
def api_call(url):
result = requests.get(url)
if not result.ok:
log.error(result, result.url)
return {}
data = result.json()
tags = {}
for entry in data["results"]:
tags[entry["name"]] = datetime.strptime(entry["last_updated"], "%Y-%m-%dT%H:%M:%S.%fZ")
tags[entry["name"]] = datetime.strptime(entry["last_updated"], "%Y-%m-%dT%H:%M:%S.%fZ") if entry["last_updated"] else "------"
if data['next']:
tags.update(api_call(data['next']))
return tags
def get_tags(image):
if "/" not in image:
image = LIB_PREFIX + image
if ":" in image:
image = image.split(":")[0]
url = TAGS.format(image=image)
tags = api_call(url)
if not len(tags):
raise ValueError(f"Unknown image '{image}'")
return tags
def replace(string, replacements):
for k,v in replacements:
string = string.replace(k,v)
return string
def compare(base, other, replacements=[("-","+"),]):
base = replace(base, replacements)
other = replace(other, replacements)
v1 = version.parse(base)
v2 = version.parse(other)
result = v1 < v2
log.debug(f"{v1} < {v2}: {result}")
return result
def get_new_tags(image):
if not ":" in image:
print("using implicit latest, skip")
log.warn("using implicit latest, skip")
return
image_name, current_tag = image.split(":")
if not image_name in TAG_STORE:
TAG_STORE[image_name] = get_tags(image_name)
if current_tag in TAG_STORE[image_name]:
first_update = TAG_STORE[image_name][current_tag]
else:
print("!!! FALLBACK!")
first_update = TAG_STORE[image_name].entry_set()[0]
print(first_update)
#if current_tag in TAG_STORE[image_name]:
# first_update = TAG_STORE[image_name][current_tag]
#else:
# print("!!! FALLBACK!")
# first_update = list(TAG_STORE[image_name].values())[0]
#print(first_update)
new_tags = {}
for tag in TAG_STORE[image_name]:
print("("+str(tag)+")")
update = TAG_STORE[image_name][tag]
if update > first_update:
log.debug("check("+str(tag)+")")
if compare(current_tag, tag):
log.debug("NEWER!!!")
update = TAG_STORE[image_name][tag]
new_tags[tag] = str(update)
log.debug(tag)
return new_tags
if __name__=="__main__":
@ -47,7 +84,7 @@ if __name__=="__main__":
args= parser.parse_args()
for i in args.image:
print(i)
log.debug(i)
if args.list:
print(json.dumps({k:str(v) for k,v in get_tags(i).items()}, indent=1))
else:

2
requirements.txt Normal file
View File

@ -0,0 +1,2 @@
requests
packaging

35
show_updateable.py Normal file
View File

@ -0,0 +1,35 @@
import argparse
import json
import docker_compose
import image_tags
def main(args):
updates = {}
images = docker_compose.start(args.compose_files, args.ignore)
for image in images:
for tag in images[image]:
image_ref = f"{image}:{tag}"
try:
newer_tags = image_tags.get_new_tags(image_ref)
except ValueError as e:
newer_tags = e.args
updates[image_ref] = {
"updates": newer_tags,
"usages": images[image][tag]
}
if args.output:
with open(args.output, "w") as out:
json.dump(updates, out, indent=1, sort_keys=True)
else:
print(json.dumps(updates, indent=1))
if __name__=="__main__":
parser = docker_compose.args_setup("Show updates for docker-compose style services")
args = parser.parse_args()
main(args)