From patchwork Fri Mar 14 19:46:16 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sergey Trofimov X-Patchwork-Id: 40188 Return-Path: X-Original-To: patchwork@mira.cbaines.net Delivered-To: patchwork@mira.cbaines.net Received: by mira.cbaines.net (Postfix, from userid 113) id 8332927BBEA; Fri, 14 Mar 2025 19:47:47 +0000 (GMT) X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on mira.cbaines.net X-Spam-Level: X-Spam-Status: No, score=-6.3 required=5.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,MAILING_LIST_MULTI,RCVD_IN_DNSWL_BLOCKED, RCVD_IN_VALIDITY_CERTIFIED,RCVD_IN_VALIDITY_RPBL,RCVD_IN_VALIDITY_SAFE, SPF_HELO_PASS,URIBL_BLOCKED,URIBL_SBL_A autolearn=ham autolearn_force=no version=3.4.6 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mira.cbaines.net (Postfix) with ESMTPS id BFEE627BBE2 for ; Fri, 14 Mar 2025 19:47:46 +0000 (GMT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ttB06-00053s-Jq; Fri, 14 Mar 2025 15:47:22 -0400 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 1ttAzp-00051z-KX for guix-patches@gnu.org; Fri, 14 Mar 2025 15:47:13 -0400 Received: from debbugs.gnu.org ([2001:470:142:5::43]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1ttAzp-0008AM-8W; Fri, 14 Mar 2025 15:47:05 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=debbugs.gnu.org; s=debbugs-gnu-org; h=MIME-Version:Date:From:To:In-Reply-To:References:Subject; bh=Hg1xQj8MfgZXpcXeoqwM5WTGx071dplv/GKTJxlYHZg=; b=MwHtwpJOZHTbmx+9P2PDoZB/izcbv2aobtY5ELnCqYX6Rx2ANerIqkW8CcnMESin6Hw4LpdNuYud2RCCKjXbDvn2p54JfkFRPzHNQ+8FyIr9MKoMOwT1NdDg+USnV4QK9rDpWa2IRFTyvnFXeYep4rTQAh7aX62B+ykRjmZj0NsmBg1pFvF1m9L4SEzAfxv0jqSm7sZRK3QKwbX7Mq7jZA31N8DjS0J344FNMJkBOk/EAhYWyZ1WpP61Htr6kpO+cZFtwm4ALbZsV6m21ben0++fgyb/4cTRKwcA15wjUJFHXOqA+sF/imKUeHmdr0QiSwR8vmYmwPOvBy094/pvRQ==; Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1ttAzm-00025u-Ka; Fri, 14 Mar 2025 15:47:02 -0400 X-Loop: help-debbugs@gnu.org Subject: [bug#77019] [PATCH] machine: hetzner: Allow attaching existing public IPs. References: In-Reply-To: Resent-From: Sergey Trofimov Original-Sender: "Debbugs-submit" Resent-CC: sarg@sarg.org.ru, ludo@gnu.org, maxim.cournoyer@gmail.com, roman@burningswell.com, guix-patches@gnu.org Resent-Date: Fri, 14 Mar 2025 19:47:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 77019 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: 77019@debbugs.gnu.org Cc: Sergey Trofimov , Sergey Trofimov , Ludovic =?utf-8?q?Court=C3=A8s?= , Maxim Cournoyer , Roman Scherer X-Debbugs-Original-Xcc: Sergey Trofimov , Ludovic =?utf-8?q?Court=C3=A8s?= , Maxim Cournoyer , Roman Scherer Received: via spool by 77019-submit@debbugs.gnu.org id=B77019.17419815998002 (code B ref 77019); Fri, 14 Mar 2025 19:47:02 +0000 Received: (at 77019) by debbugs.gnu.org; 14 Mar 2025 19:46:39 +0000 Received: from localhost ([127.0.0.1]:36351 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1ttAzK-00024q-D6 for submit@debbugs.gnu.org; Fri, 14 Mar 2025 15:46:38 -0400 Received: from mail-ej1-x635.google.com ([2a00:1450:4864:20::635]:43098) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.84_2) (envelope-from ) id 1ttAzG-00024T-6H for 77019@debbugs.gnu.org; Fri, 14 Mar 2025 15:46:32 -0400 Received: by mail-ej1-x635.google.com with SMTP id a640c23a62f3a-ac297cbe017so644989866b.0 for <77019@debbugs.gnu.org>; Fri, 14 Mar 2025 12:46:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sarg.org.ru; s=google; t=1741981583; x=1742586383; darn=debbugs.gnu.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=Hg1xQj8MfgZXpcXeoqwM5WTGx071dplv/GKTJxlYHZg=; b=pWnoTaStN+WaN3B50qQi0wY8wsZv9QNl0UzhZZhxXLRMggfMBWJ95u33iDvh82zMtw s+0fkYY1aFD44hzPIzX2bmBKJkff+OOaWvCmPHfy/aJ9FsyhOwqrsUmgw2rg17n2shFo DQzte66NT/FOU7wNpEFyZDNPPzUEVIXuRa/5cMlZLn5tteqOe677AWo2e9XPo8Q/rVQS xsAfII79HRHEwsXfIbMI7PEKYMjUMFR7ErQwJqoSWnUHC5sAWLluWewwzgzKxjlBcxNC Nbz2BCiiKqGYIprXalThffJAvxXKC/kZ7mtK4AcaImq1NW1f0zoumDmSg27PEvhMpLiY lUCg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741981583; x=1742586383; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=Hg1xQj8MfgZXpcXeoqwM5WTGx071dplv/GKTJxlYHZg=; b=G/o59vm7Iun/PFkTZDQ8opVTETgpRFBjcBM5a5y3UqKH7Rmpw7AZG8nz3s1qon/7ms +Y1GuHiFWpGw62hR3fGedU/qC5ZQEsToMp5CG3BycFWYhq7kQfvqaLpOK3Wbt6/RMA5A HXrdGxw5DU6Xy4gLTfomQl17T0Z0xJlEJO2ejGTtx1ebhGkwaXpbWkDtMK+ZivsWEhcI 3UEJdXY1wtlc3+gIp7DN/PYXdagm/NhErsfAoJpnfdYVWvROtJrmZ2kFs6KZ+7xLyeE8 z9c3bVvEFX47dDFHVkIH/vX/pqYksYYCcuVUya59gNa6FS8zpLuTryvlvku3tdXjcGzO fg0Q== X-Gm-Message-State: AOJu0YzoEKRWgpOq1tnf+yzJ2Ojj31uq3LKpw6E+Ego61evtA0d/qNL3 We/Sue6LrjIwQ5EqNEg8lTD1oIIB1AhoaDcF9T5lagnzUjX3HwIC2KCtiFjkbUknxodnnYr/ig9 oc58= X-Gm-Gg: ASbGncvY7D/UqtDgJPYqJWNM1ljpCQv7eEU0PfdDlxpP9SG9fYuxp3tZpKuwjOaML/D BP5ZM9PxTHdmkJGPlhLNwfXaGIyNa7yk5X0P9cznLbwjvVz6P0AOCkARbjtVa/75JI0TpQGet5i 9bpTahP51uxqmY+XpeJ4+13hrQ8wojEZQ8/wt5XPeVEThZGu5+UbLEU0pnqnyLI/Xkp5FDhxiA8 vgHXyzk5Hwnh20BX5u26nVj0isTeoKJ9tf8x/9qF9z4ne+JXe/D+udn8pLrr3+sQ0VMaxVWIFUy BnLedZzsvyFF5kDPEf4y0WYeDwyWx9dVb3M/Z/Mu/YJjn/42b92A X-Google-Smtp-Source: AGHT+IFT5FSz7nP3N4wMGmVSUE9x4qVvYzqO/PvDs/p9ijwf86VCZJ3X8ZSvmEBKhKXH4qMV4oOwHA== X-Received: by 2002:a17:907:7fa6:b0:abf:742e:1fde with SMTP id a640c23a62f3a-ac331377bf4mr431426966b.14.1741981582690; Fri, 14 Mar 2025 12:46:22 -0700 (PDT) Received: from localhost ([2a02:2454:a0a5:2400:a64e:31ff:fe38:fd6c]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-ac3147f142fsm266414266b.64.2025.03.14.12.46.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 14 Mar 2025 12:46:22 -0700 (PDT) Date: Fri, 14 Mar 2025 20:46:16 +0100 Message-ID: <9f04c5e5955ef1115effce2f3b332091ec149b2a.1741981547.git.sarg@sarg.org.ru> X-Mailer: git-send-email 2.48.1 MIME-Version: 1.0 X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: guix-patches@gnu.org List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-to: Sergey Trofimov X-ACL-Warn: , Sergey Trofimov via Guix-patches X-Patchwork-Original-From: Sergey Trofimov via Guix-patches via From: Sergey Trofimov Errors-To: guix-patches-bounces+patchwork=mira.cbaines.net@gnu.org Sender: guix-patches-bounces+patchwork=mira.cbaines.net@gnu.org X-getmail-retrieved-from-mailbox: Patches * gnu/machine/hetzner.scm (hetzner-configuration): Add ipv4 and ipv6 fields. Export accessors. * gnu/machine/hetzner/http.scm (hetnzer-api-primary-ips): New function. (): New json mapping. (hetzner-api-server-create): Pass IP addresses in request. * doc/guix.texi: Document it. --- doc/guix.texi | 10 ++++++++++ gnu/machine/hetzner.scm | 25 +++++++++++++++++++++++++ gnu/machine/hetzner/http.scm | 35 +++++++++++++++++++++++++++++------ 3 files changed, 64 insertions(+), 6 deletions(-) base-commit: 412f411d4f8780e6b60b448caae17f01c09be0eb -- 2.48.1 diff --git a/doc/guix.texi b/doc/guix.texi index 49ac018913..4a35f3ea13 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -45919,6 +45919,16 @@ Invoking guix deploy provisioning phase. If false, the server will be kept in order to debug any issues. +@item @code{ipv4} (default: @code{'create}) +When false, no public IPv4 address is going to be attached. Specify the +name of an existing primary ip to attach it to the machine. Other values +would create a new address automatically. + +@item @code{ipv6} (default: @code{'create}) +When false, no public IPv6 address is going to be attached. Specify the +name of an existing primary ip to attach it to the machine. Other values +would create a new address automatically. + @item @code{labels} (default: @code{'()}) A user defined alist of key/value pairs attached to the SSH key and the server on the Hetzner API. Keys and values must be strings, diff --git a/gnu/machine/hetzner.scm b/gnu/machine/hetzner.scm index e8484e4d51..c1ccab54ae 100644 --- a/gnu/machine/hetzner.scm +++ b/gnu/machine/hetzner.scm @@ -73,6 +73,8 @@ (define-module (gnu machine hetzner) hetzner-configuration-authorize? hetzner-configuration-build-locally? hetzner-configuration-delete? + hetzner-configuration-ipv4 + hetzner-configuration-ipv6 hetzner-configuration-labels hetzner-configuration-location hetzner-configuration-server-type @@ -205,6 +207,10 @@ (define-record-type* hetzner-configuration (default "fsn1")) (server-type hetzner-configuration-server-type ; string (default "cx42")) + (ipv4 hetzner-configuration-ipv4 + (default 'create)) + (ipv6 hetzner-configuration-ipv6 + (default 'create)) (ssh-public-key hetzner-configuration-ssh-public-key ; public-key | string (thunked) (default (public-key-from-file (hetzner-configuration-ssh-key this-hetzner-configuration))) @@ -445,6 +451,17 @@ (define (hetzner-machine-server machine) (hetzner-configuration-api config) #:params `(("name" . ,(machine-display-name machine))))))) +(define (hetzner-resolve-ip api name) + "Find the NAME IP address on the Hetzner API." + (or + (find (lambda (primary-ip) + (equal? name (hetzner-primary-ip-name primary-ip))) + (hetzner-api-primary-ips api #:params `(("name" . ,name)))) + + (raise-exception + (formatted-message (G_ "primary ip '~a' does not exist.") + name)))) + (define (hetzner-machine-create-server machine) "Create the Hetzner server for MACHINE." (let* ((config (machine-configuration machine)) @@ -452,11 +469,19 @@ (define (hetzner-machine-create-server machine) (server-type (hetzner-configuration-server-type config))) (format #t "creating '~a' server for '~a'...\n" server-type name) (let* ((ssh-key (hetzner-machine-ssh-key machine)) + (ipv4 (hetzner-configuration-ipv4 config)) + (ipv6 (hetzner-configuration-ipv6 config)) (api (hetzner-configuration-api config)) (server (hetzner-api-server-create api (machine-display-name machine) (list ssh-key) + #:ipv4 (if (string? ipv4) + (hetzner-primary-ip-id (hetzner-resolve-ip api ipv4)) + ipv4) + #:ipv6 (if (string? ipv6) + (hetzner-primary-ip-id (hetzner-resolve-ip api ipv6)) + ipv4) #:labels (hetzner-configuration-labels config) #:location (hetzner-configuration-location config) #:server-type (hetzner-configuration-server-type config))) diff --git a/gnu/machine/hetzner/http.scm b/gnu/machine/hetzner/http.scm index 51b4bff984..6a82558fbe 100644 --- a/gnu/machine/hetzner/http.scm +++ b/gnu/machine/hetzner/http.scm @@ -52,6 +52,7 @@ (define-module (gnu machine hetzner http) hetzner-api-actions hetzner-api-create-ssh-key hetzner-api-locations + hetzner-api-primary-ips hetzner-api-request-body hetzner-api-request-headers hetzner-api-request-method @@ -100,6 +101,13 @@ (define-module (gnu machine hetzner http) hetzner-location-name hetzner-location-network-zone hetzner-location? + hetzner-primary-ip + hetzner-primary-ip-created + hetzner-primary-ip-id + hetzner-primary-ip-ip + hetzner-primary-ip-labels + hetzner-primary-ip-name + hetzner-primary-ip-type hetzner-public-net hetzner-public-net-ipv4 hetzner-public-net-ipv6 @@ -296,6 +304,15 @@ (define-json-mapping (name hetzner-server-type-name) ; string (storage-type hetzner-server-type-storage-type "storage_type")) ; string +(define-json-mapping + make-hetzner-primary-ip hetzner-primary-ip? json->hetzner-primary-ip + (created hetzner-primary-ip-created "created" string->time) ; time + (id hetzner-primary-ip-id) ; integer + (ip hetzner-primary-ip-ip) ; string + (labels hetzner-primary-ip-labels) ; alist of string/string + (name hetzner-primary-ip-name) ; string + (type hetzner-primary-ip-type)) ; string + (define-json-mapping make-hetzner-ssh-key hetzner-ssh-key? json->hetzner-ssh-key (created hetzner-ssh-key-created "created" string->time) ; time @@ -581,12 +598,11 @@ (define* (hetzner-api-locations api . options) (define* (hetzner-api-server-create api name ssh-keys #:key - (enable-ipv4? #t) - (enable-ipv6? #t) + (ipv4 #f) + (ipv6 #f) (image %hetzner-default-server-image) (labels '()) (location %hetzner-default-server-location) - (public-net #f) (server-type %hetzner-default-server-type) (start-after-create? #f)) "Create a server with the Hetzner API." @@ -595,9 +611,11 @@ (define* (hetzner-api-server-create #:body `(("image" . ,image) ("labels" . ,labels) ("name" . ,name) - ("public_net" - . (("enable_ipv4" . ,enable-ipv4?) - ("enable_ipv6" . ,enable-ipv6?))) + ("public_net" . + (("enable_ipv4" . ,(and ipv4 #t)) + ("enable_ipv6" . ,(and ipv6 #t)) + ,@(if (integer? ipv4) `(("ipv4" . ,ipv4)) '()) + ,@(if (integer? ipv6) `(("ipv6" . ,ipv6)) '()))) ("location" . ,location) ("server_type" . ,server-type) ("ssh_keys" . ,(apply vector (map hetzner-ssh-key-id ssh-keys))) @@ -658,6 +676,11 @@ (define* (hetzner-api-ssh-keys api . options) (apply hetzner-api-list api "/ssh_keys" "ssh_keys" json->hetzner-ssh-key options)) +(define* (hetzner-api-primary-ips api . options) + "Get Primary IPs from the Hetzner API." + (apply hetzner-api-list api "/primary_ips" "primary_ips" + json->hetzner-primary-ip options)) + (define* (hetzner-api-server-types api . options) "Get server types from the Hetzner API." (apply hetzner-api-list api "/server_types" "server_types"