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@redhat.com>
---
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@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
On Thu, Jul 12, 2018 at 05:19:29PM +0200, Andrea Bolognani wrote:
> 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@redhat.com>
> ---
> 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":
More pythonic would be "package_format not in ('deb', '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@redhat.com
> https://www.redhat.com/mailman/listinfo/libvir-list
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
© 2016 - 2026 Red Hat, Inc.