This is basically the exact same algorithm used by the Ansible playbooks to process package mappings, implemented in pure Python. Signed-off-by: Andrea Bolognani <abologna@xxxxxxxxxx> --- guests/lcitool | 86 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 80 insertions(+), 6 deletions(-) diff --git a/guests/lcitool b/guests/lcitool index d42b7e7..61cae97 100755 --- a/guests/lcitool +++ b/guests/lcitool @@ -299,7 +299,10 @@ class Application: hosts list all known hosts projects list all known projects - glob patterns are supported for HOSTS + uncommon actions: + dockerfile generate Dockerfile (doesn't access the host) + + glob patterns are supported for HOSTS and PROJECTS """), ) self._parser.add_argument( @@ -313,16 +316,21 @@ class Application: metavar = "HOSTS", help = "list of hosts to act on", ) + self._parser.add_argument( + "-p", + metavar = "PROJECTS", + help = "list of projects to consider", + ) - def _action_list(self, hosts): + def _action_hosts(self, hosts, projects): for host in self._inventory.expand_pattern("all"): print(host) - def _action_projects(self, hosts): + def _action_projects(self, hosts, projects): for project in self._projects.expand_pattern("all"): print(project) - def _action_install(self, hosts): + def _action_install(self, hosts, projects): flavor = self._config.get_flavor() for host in self._inventory.expand_pattern(hosts): @@ -380,7 +388,7 @@ class Application: except: raise Error("Failed to install '{}'".format(host)) - def _action_update(self, hosts): + def _action_update(self, hosts, projects): flavor = self._config.get_flavor() vault_pass_file = self._config.get_vault_password_file() root_pass_file = self._config.get_root_password_file() @@ -409,15 +417,81 @@ class Application: except: raise Error("Failed to update '{}'".format(hosts)) + def _action_dockerfile(self, hosts, projects): + mappings = self._projects.get_mappings() + + hosts = self._inventory.expand_pattern(hosts) + if len(hosts) > 1: + raise Error("Can't generate Dockerfile for multiple hosts") + host = hosts[0] + + facts = self._inventory.get_facts(host) + package_format = facts["package_format"] + os_name = facts["os_name"] + os_full = os_name + str(facts["os_version"]) + + if package_format != "deb" and package_format != "rpm": + raise Error("Host {} doesn't support Dockerfiles".format(host)) + + projects = self._projects.expand_pattern(projects) + for project in projects: + if project not in facts['projects']: + raise Error( + "Host {} doesn't support project {}".format( + host, + project, + ) + ) + + temp = {} + + # We need to add the base project manually here: the standard + # machinery hides it because it's an implementation detail + for project in projects + [ "base" ]: + for package in self._projects.get_packages(project): + if "default" in mappings[package]: + temp[package] = mappings[package]["default"] + if package_format in mappings[package]: + temp[package] = mappings[package][package_format] + if os_name in mappings[package]: + temp[package] = mappings[package][os_name] + if os_full in mappings[package]: + temp[package] = mappings[package][os_full] + + flattened = [] + for item in temp: + if temp[item] != None and temp[item] not in flattened: + flattened += [ temp[item] ] + + print("FROM {}".format(facts['docker_base'])) + + sys.stdout.write("ENV PACKAGES ") + sys.stdout.write(" \\\n ".join(sorted(flattened))) + + if package_format == "deb": + sys.stdout.write(textwrap.dedent(""" + RUN apt-get update && \\ + apt-get install -y ${PACKAGES} && \\ + apt-get autoremove -y && \\ + apt-get autoclean -y + """)) + elif package_format == "rpm": + sys.stdout.write(textwrap.dedent(""" + RUN yum install -y ${PACKAGES} && \\ + yum autoremove -y && \\ + yum clean all -y + """)) + def run(self): cmdline = self._parser.parse_args() action = cmdline.a hosts = cmdline.h + projects = cmdline.p method = "_action_{}".format(action.replace("-", "_")) if hasattr(self, method): - getattr(self, method).__call__(hosts) + getattr(self, method).__call__(hosts, projects) else: raise Error("Invalid action '{}'".format(action)) -- 2.17.1 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list