From 446b8f4a8ef78cb4605cfb551255bb455be411f0 Mon Sep 17 00:00:00 2001 From: Sean Whitton Date: Thu, 16 Sep 2021 18:23:55 -0700 Subject: install system deps by searching for package managers on PATH With this change we handle the situation in which we don't know the OS of a host on which we need to install system packages more cleanly than before. Also rely on the new PACKAGE:INSTALLED to install the OS bootstrapper in INSTALLER:CLEANLY-INSTALLED-ONCE. This allows us to simplify usage of the property by replacing the ORIGINAL-OS argument with ORIGINAL-OS-ARCHITECTURE. Making this change does mean that we now have two ways to specify the different names a package has on different OSs: (i) something like OS:ETYPECASE where each branch applies a property which invokes an OS-specific package manager; and (ii) the plists supplied to PACKAGE:INSTALLED. Signed-off-by: Sean Whitton --- src/property/package.lisp | 88 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 src/property/package.lisp (limited to 'src/property/package.lisp') diff --git a/src/property/package.lisp b/src/property/package.lisp new file mode 100644 index 0000000..9e3d480 --- /dev/null +++ b/src/property/package.lisp @@ -0,0 +1,88 @@ +;;; Consfigurator -- Lisp declarative configuration management system + +;;; Copyright (C) 2021 Sean Whitton + +;;; This file is free software; you can redistribute it and/or modify +;;; it under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3, or (at your option) +;;; any later version. + +;;; This file is distributed in the hope that it will be useful, +;;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. + +;;; You should have received a copy of the GNU General Public License +;;; along with this program. If not, see . + +(in-package :consfigurator.property.package) +(named-readtables:in-readtable :consfigurator) + +(defparameter *consfigurator-system-dependencies* '(:apt "build-essential")) + +(defgeneric %command (package-manager) + (:documentation + "Returns a command which, if found on PATH, indicates that the system package +manager identified by PACKAGE-MANAGER is available.")) + +(defmethod %command ((package-manager (eql :apt))) + "apt-get") + +(defgeneric %installed (package-manager packages) + (:documentation + "Install each of PACKAGES using the system package manager identified by +PACKAGE-MANAGER. + +Implementations should not fail just because we are not root, or otherwise +privileged, if the package is already installed.")) + +(defmethod %installed ((package-manager (eql :apt)) packages) + ;; Call PROPAPPAPPLY directly because we want the :CHECK subroutine run, but + ;; it does not make sense to run the :HOSTATTRS subroutine because *HOST* + ;; does not necessarily correspond to the host we're attempting to install + ;; packages on. + (propappapply `(apt:installed ,@packages))) + +(define-simple-error package-manager-not-found (aborted-change)) + +(defprop installed :posix + (package-manager &rest package-lists &aux package-list) + "Attempt to use a system package manager to install system packages as +specified by PACKAGE-LISTS. If PACKAGE-MANAGER, a keyword, use that +particular package manager; otherwise, see what we can find on PATH. + +Each of PACKAGE-LISTS is a plist where the keys identify package managers, and +where the values are lists of package names to install using that package +manager. See PACKAGE:*CONSFIGURATOR-SYSTEM-DEPENDENCIES* for an example. + +This property should not typically be applied to hosts. It is preferable to +use an operating system-specific property, such as APT:INSTALLED. This +property exists because in a few cases it is necessary to install packages +where there is no known-valid HOST value for the machine upon which we need to +install packages, and thus we cannot infer what package manager to use from +the host's OS, and must fall back to seeing what's on PATH. + +In particular, when starting up a remote Lisp image when the REMAINING +argument to ESTABLISH-CONNECTION is non-nil, we might be starting up Lisp on a +machine other than the one to be deployed and we do not have HOST values for +intermediate hops. Another case is INSTALLED:CLEANLY-INSTALLED-ONCE; +regardless of REMAINING, the initial OS might be the one we will replace, not +the declared OS for the host." + (:apply + (dolist (list package-lists) + (doplist (k v list) + (dolist (p (ensure-cons v)) + (push p (getf package-list k))))) + (loop with reversed + for (k v) on package-list by #'cddr + do (push v reversed) (push k reversed) + finally (setq package-list reversed)) + (if package-manager + (return-from installed + (%installed package-manager (getf package-list package-manager))) + (doplist (package-manager packages package-list) + (when (remote-executable-find (%command package-manager)) + (return-from installed (%installed package-manager packages))))) + (package-manager-not-found + "Could not find any package manager on PATH with which to install ~S." + package-list))) -- cgit v1.2.3