From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mp10.migadu.com ([2001:41d0:2:bcc0::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by ms9.migadu.com with LMTPS id /rsZEVVECWQWqwAASxT56A (envelope-from ) for ; Thu, 09 Mar 2023 03:28:37 +0100 Received: from aspmx1.migadu.com ([2001:41d0:2:bcc0::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp10.migadu.com with LMTPS id gO5ZD1VECWRJngAAG6o9tA (envelope-from ) for ; Thu, 09 Mar 2023 03:28:37 +0100 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by aspmx1.migadu.com (Postfix) with ESMTPS id B8F9C3183A for ; Thu, 9 Mar 2023 03:28:36 +0100 (CET) Authentication-Results: aspmx1.migadu.com; dkim=none; spf=pass (aspmx1.migadu.com: domain of "guix-devel-bounces+larch=yhetil.org@gnu.org" designates 209.51.188.17 as permitted sender) smtp.mailfrom="guix-devel-bounces+larch=yhetil.org@gnu.org"; dmarc=none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=yhetil.org; s=key1; t=1678328917; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding:list-id:list-help: list-unsubscribe:list-subscribe:list-post; bh=+hMXtePPbegmpn/PjS/Gi/6zJ8YZrJ1B7RxkzybrQx8=; b=D069cdbg55Pz+Et9m6Aw8195uoN8f8n1ibCR+N6UQARhPOQq9DZSz0N6tzPhGLh5TX4FU7 /Y50JzgvhnoCZpLZIQWDjxKkTggOiulV9Zth7PRuIA+SRTTmRvus4N0Fzj/SkEM8FQCk8v WHt/KXchJ7XfTajf3F/5O2OxEVF1s+ohfUPFIqDOACTJvc/n2HOATIzJv2GHjOlLnbLlm6 hOGBRM5iRB1MobDR3w7twdGizJXEx6U27fTpgRcoAswqiFrXnGPETQB/zmr1VDwwRMU4r6 LsaiSHuCGzbgYBnGoKe7M7p4unXX+B5zGa2kDegZcyjFcA8e0k3Teu9Q2JXWaQ== ARC-Seal: i=1; s=key1; d=yhetil.org; t=1678328917; a=rsa-sha256; cv=none; b=q5UR2nUvhLIldqzdAMHqvPSXM26CafK/zO5JlA5mA1nDIfMHQW5nXqwI8STZBUTvHJzbX4 4Y1m3fWD5s+WthjU+Mv2a8u/hnmL0Jq85VLf9rKsn+tZZut7d8hoMAljlWxw7K4B8D6jQZ H6ZN8uJQxux6svZH4w8gl5jjtc2uQyf13W0CPE2pDr3SmqMWvGZxTCpaXbumpm0yNt+QRb Z92TeoGW3+iGdZepABQX/MyuT+6lpoUGXWC5oWKLO+0BZIDdrn00LuQ+LllrNkFzXrO7f5 BhmDuSWimgpljUNmklkcwDanqFmh9aGWhwlLO5sPCABUpB19VEi3fJaiNUoutA== ARC-Authentication-Results: i=1; aspmx1.migadu.com; dkim=none; spf=pass (aspmx1.migadu.com: domain of "guix-devel-bounces+larch=yhetil.org@gnu.org" designates 209.51.188.17 as permitted sender) smtp.mailfrom="guix-devel-bounces+larch=yhetil.org@gnu.org"; dmarc=none Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pa60p-0004Qf-Ia; Wed, 08 Mar 2023 21:28:11 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pa60n-0004QD-Pd for guix-devel@gnu.org; Wed, 08 Mar 2023 21:28:09 -0500 Received: from smtpmciv1.myservices.hosting ([185.26.107.237]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pa60l-0003wL-Bf; Wed, 08 Mar 2023 21:28:09 -0500 Received: from mail1.netim.hosting (unknown [185.26.106.173]) by smtpmciv1.myservices.hosting (Postfix) with ESMTP id AAC6C20D11; Thu, 9 Mar 2023 03:28:02 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by mail1.netim.hosting (Postfix) with ESMTP id 567038009D; Thu, 9 Mar 2023 03:28:02 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at mail1.netim.hosting Received: from mail1.netim.hosting ([127.0.0.1]) by localhost (mail1-2.netim.hosting [127.0.0.1]) (amavisd-new, port 10026) with ESMTP id TfUopsA9odPi; Thu, 9 Mar 2023 03:28:01 +0100 (CET) Received: from [192.168.1.239] (unknown [10.192.1.83]) (Authenticated sender: lumen@makinata.eu) by mail1.netim.hosting (Postfix) with ESMTPSA id 7770880098; Thu, 9 Mar 2023 03:28:01 +0100 (CET) Message-ID: Date: Thu, 9 Mar 2023 02:28:01 +0000 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.8.0 Content-Language: en-US Cc: Felix Lechner , mirai , Liliana Marie Prikler , Maxim Cournoyer , =?UTF-8?Q?Ludovic_Court=c3=a8s?= From: Bruno Victal Subject: Brainstorming ideas for define-configuration To: guix-devel Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit Received-SPF: pass client-ip=185.26.107.237; envelope-from=mirai@makinata.eu; helo=smtpmciv1.myservices.hosting X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: guix-devel@gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "Development of GNU Guix and the GNU System distribution." List-Unsubscribe: , List-Archive: List-Post: X-Migadu-Scanner: scn0.migadu.com X-Migadu-Queue-Id: B8F9C3183A X-Spam-Score: -1.50 X-Migadu-Spam-Score: -1.50 List-Help: List-Subscribe: , Errors-To: guix-devel-bounces+larch=yhetil.org@gnu.org Sender: guix-devel-bounces+larch=yhetil.org@gnu.org X-Migadu-Flow: FLOW_IN X-Migadu-Country: US X-TUID: zqh9dKjierpy Co-authored-by: Felix Lechner After spending some time with old and new Guix services, I'd like to suggest some potential improvements to our define-configuration macro: User-specified sanitizer support =============================================================================== The sanitizers should be integrated with the type. Otherwise, they are tedious to use and appear verbose when repeatedly applied to multiple fields. --8<---------------cut here---------------start------------->8--- ;; Suggestion #1 ;; The procedure could return a sanitized value. Upon failure, there are ;; the following options: ;; - The procedure returns only a special value (akin to %unset-value) ;; and an error message, as a pair. ;; Exception raising is done by define-sanitized macro behind the scenes ;; which makes the procedure easier to write. ;; - The procedure raises an exception. There would be no consistency ;; on the message formats, however, except for any agreed convention. ;; This would involve some code duplication. ;; Cons: too specific, not extensible. (define-sanitized typename procedure (prefix ...)) ;; Suggestion #2 ;; A user-supplied procedure ('procname' below) would work just like the ;; procedure in option #1. ;; There is some similiarity to the Guix record-type*. ;; This could be extended more easily in the future should it be required. (define-type typename ; maybe call this 'define-configuration-type' ? (sanitizer procname) (maybe-type? #t) ;; The properties below are service specific. ;; If this is implemented with Guix record-type* then we could have a ;; module containing generic types and do something along the lines of: ;; (define-type foo-ip-address ;; (inherit generic-ip-address) ;; (serializer ...)) (serializer procname) ; define-type/no-serialization = sets this field to #f ? (prefix ...)) --8<---------------cut here---------------end--------------->8--- The original motivation for this proposal stems from the attempts to resolve issue #61570. There, one potential fix was to handle the user and group fields similarly to the way greetd service handles them. There is some opportunity for generalization here, types that might be useful elsewhere, such as a port number or a host name, could be placed in a separate module. This proposal should also make it easier to handle situations when fields become obsolete. Record Validator =============================================================================== There is also a need to validate records. Matching fields alone do not actually ensure that the configuration is coherent and usable. For example, some fields may be mutually incompatible with others. We could provide procedures that validate each record type within define-configuration itself instead of validating the value at runtime (i.e. within the body of the service-type). --8<---------------cut here---------------start------------->8--- ;; the common case (define-configuration foo-configuration (name string "Lorem ipsum...") ;; ... (validator procname)) ;; [bonus] Simpler configurations that only care for mutually-exclusive fields (define-configuration foo-configuration (name string "Lorem ipsum...") (title string "Lorem ipsum..." (conflicts 'name))) --8<---------------cut here---------------end--------------->8--- Comments regarding literal placement ------------------------------------------------------------------------------- Does the placement order matter for the extra fields/literals for define-configuration? Can they be placed arbitrarily or only at the bottom? (where custom-serializer is specified) Another point, extra parameters given to define-configuration should never clash with field names. For example, it should be possible to name a field 'prefix', 'location' or similar without causing issues like #59423. Coalesced documentation =============================================================================== Currently, we manually edit the texinfo output from configuration->documentation if we're unsatisfied with the generated result. For instance, substituting @item with an @itemx marker for fields whose documentation is similar. Instead, we could embed hints in define-configuration that affect the texinfo generation in smarter ways. In the long term, guix.texi should source some portions of the documentation directly from the code base. The current workflow involving copy and paste the output from the evaluation of configuration->documentation carries the unnecessary risk that future documentation patches are done against guix.texi rather than the .scm file from where it was generated. (issue #60582) Snippet based on mympd-ip-acl (gnu/services/audio.scm): --8<---------------cut here---------------start------------->8--- (define-configuration/no-serialization mympd-ip-acl (allow (list-of-string '()) "Allowed/Disallowed IP addresses.") (deny (list-of-string '()) (documentation 'allow))) ; group with field 'allow ;;; --- texi output below --- @c %start of fragment @deftp {Data Type} mympd-ip-acl Available @code{mympd-ip-acl} fields are: @table @asis @item @code{allow} @itemx @code{deny} (default: @code{()}) (type: list-of-string) Allowed/Disallowed IP addresses. @end table @end deftp @c %end of fragment --8<---------------cut here---------------end--------------->8--- Serializer access to other fields =============================================================================== Serialization procedures generally only have access to the values of its own field. That may be insufficient in some cases as whether a field can be serialized or how that is done, for example, can depend on the value of other fields. mympd-service-type is one example where each serialized field depends on the value of another field. Our standard serializer procedures were useless for that case. As a side note, the 'this-record' macro does not work with define-configuration which made it impossible to use (custom-serializer) for the same effect. Instead, serializer procedures could take additional keyword arguments: --8<---------------cut here---------------start------------->8--- (define* (serialize-string field-name value (#:key config)) (let ((baz-value (assoc-ref config 'baz))) (string-append baz-value "/" value) ...)) --8<---------------cut here---------------end--------------->8--- Inheritable record-type definition =============================================================================== The openvpn-service pairs in (gnu services vpn) define a special macro define-split-configuration with the purpose to avoid code duplication since the service pairs have multiple fields in common. Perhaps in a similar vein to SRFI-136, we could have: --8<---------------cut here---------------start------------->8--- (define-configuration openvpn-common-configuration (openvpn (file-like openvpn) "The OpenVPN package.") ;; ... ) (define-configuration openvpn-server-configuration openvpn-common-configuration (tls-auth (tls-auth-server #f) "Add an additional layer of HMAC authentication on top of the TLS control channel to protect against DoS attacks.") ;; ... ) ;;; or through a literal/keyword approach (define-configuration openvpn-server-configuration (tls-auth (tls-auth-server #f) "Add an additional layer of HMAC authentication on top of the TLS control channel to protect against DoS attacks.") (parent openvpn-common-configuration)) --8<---------------cut here---------------end--------------->8--- Generic serialize-configuration =============================================================================== The procedure serialize-configuration inherently assumes that the serialized configuration must be a single string. This assumption needn't always hold, especially if the service in question is not a shepherd service. We could possibly make this procedure a bit more "generic", maybe picking some ideas from SRFI-171 Transducers. Another improvement to this procedure is to eliminate (or make optional) the second parameter, the configuration fields. It's unclear what value it brings since one can't use fields from another configuration type here. An argument can be made for selectively serializing some of the fields but then it would be more practical to make this an optional parameter. PS. =============================================================================== Kind of a late realization, but couldn't many of the items above be satisfied by improvements to define-record-type* instead? (define-record-type* paired with a documentation literal is nearly equivalent to define-configuration, sans the serialization scaffolding) Cheers, Bruno