From 50e826b0317652390b23aa26ade60095b673173f Mon Sep 17 00:00:00 2001 From: Adam Miller Date: Oct 25 2017 16:18:57 +0000 Subject: add module to identify layered image inheritance Created a module that will take fedora release and a list of layered images (meant to be provided by the fedcontainer_rc module but can originate from anywhere) and will provide a dictionary where they keys are the parent images and the value is a list of children images. This will assist in automating the layered image rebuild process. Signed-off-by: Adam Miller --- diff --git a/ansible/fedcontainer_inheritance_demo.yml b/ansible/fedcontainer_inheritance_demo.yml new file mode 100644 index 0000000..4ed2224 --- /dev/null +++ b/ansible/fedcontainer_inheritance_demo.yml @@ -0,0 +1,19 @@ +--- +- name: fedcontainer_inheritance demo + hosts: automator + vars: + fedora_release: 26 + tasks: + - name: Gather list of releases + fedcontainer_rc: + release: "{{fedora_release}}" + register: query_data + + - name: Determine parent image inheritance + fedcontainer_inheritance: + release: "{{fedora_release}}" + layered_images: "{{query_data.rebuildlist}}" + register: image_inheritance + + - debug: var=image_inheritance["parent_children"] + - debug: var=image_inheritance["errors"] diff --git a/ansible/library/fedcontainer_inheritance.py b/ansible/library/fedcontainer_inheritance.py new file mode 100755 index 0000000..0d45cd4 --- /dev/null +++ b/ansible/library/fedcontainer_inheritance.py @@ -0,0 +1,134 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# fedcontainer_inheritance.py - Ansible module to gather Fedora container image +# inheritance. This will return a dict. +# +# Copyright (C) 2017 Red Hat, Inc. +# SPDX-License-Identifier: GPL-2.0+ +# +# Authors: +# Adam Miller +# + +DOCUMENTATION = ''' +--- +author: + - "Adam Miller " +module: fedcontainer_inheritance +short_description: Query Container Parent Image Inheritance +description: + - Query Container Parent Image Inheritance + - Returns dict entry 'parent_children' in return JSON, which will contain a + dict where the keys are the parent images and the values are the children + images. +options: + release: + description: + - Fedora Release number + required: true + layered_images: + description: + - List of layered images that need their inheritance identified +''' + +EXAMPLES = ''' +# Generally meant to be used with other tasks as input, registry the output var +- fedcontainer_inheritance: + release: 26 + register: image_inheritance + +- debug: var=image_inheritance["parent_children"] + + +# More "full featured" example using the fedcontainer_rc module as input +- name: Gather list of releases + fedcontainer_rc: + release: 26 + register: query_data + +- name: Determine parent image inheritance + fedcontainer_inheritance: + release: 26 + layered_images: "{{query_data.rebuildlist}}" + register: image_inheritance + +- debug: var=image_inheritance["parent_children"] +''' + + +################################################## +# import module snippets +from ansible.module_utils.basic import * + +import re + +try: + import requests +except ImportError: + module.fail_json("requests python module not found but is required") + +def main(): + + depchain = {} + errors = [] + + query_url = "https://src.fedoraproject.org/container/{}/raw/f{}/f/Dockerfile" + + # Define the module and parameters + module = AnsibleModule( + argument_spec=dict( + release=dict(required=True, type="int", default=None), + layered_images=dict(required=True, type="list", default=None), + ), + supports_check_mode=False + ) + + for container in module.params["layered_images"]: + + # Grab the contents of the Dockerfile + r = requests.get(query_url.format(container, module.params["release"])) + + # list comprehension to filter out the FROM line, it's a little overkill + # and a little hacky, but it is considerably faster than alternatives. + # + try: + # The logic here is that the list comprehension returns a list + # which contains a single element (which we know it will because a + # Dockerfile can only have one FROM line), then we look at the + # string at index 0 (which is the only thing in the list) and split + # it over whitespace and reference the last element, which will be + # the parent image of this layered image's Dockerfile. + parent_image = [ + element for element in r.content.split("\n") + if 'FROM' in element + ][0].split()[-1] + + # Now we will filter out to make sure that the base images are all + # grouped together since they can technically be referenced + # short-hand and long form in the FROM line. + base_img_key = "fedora:{}".format(module.params["release"]) + pattern = re.compile(".*{}$".format(base_img_key)) + if pattern.match(parent_image): + parent_base_img_key = [ + key for key in depchain.keys() + if pattern.match(key) + ] + if parent_base_img_key: + parent_image = parent_base_img_key[0] + + depchain.setdefault(parent_image, []) + depchain[parent_image].append(container) + except IndexError: + errors.append(r.content) + + + module.exit_json( + changed=False, + msg="Successfully identified container image inheritance, results in 'parent_children'", + parent_children=depchain, + errors=errors + ) + +main() +# vim: set expandtab sw=4 sts=4 ts=4