diff options
| author | Maxim Cournoyer <maxim@guixotic.coop> | 2026-05-01 23:38:31 +0900 |
|---|---|---|
| committer | Maxim Cournoyer <maxim@guixotic.coop> | 2026-05-23 13:29:15 +0900 |
| commit | f98c00ab749e6b82e56a4a34d0789496451cbc59 (patch) | |
| tree | dee7cd04af676a3b0a59fe888c498740d43161a7 /gnu | |
| parent | 5d3305955041992576fd5ccc9852ab5b78d5c284 (diff) | |
machine: Dynamically retrieve the base server image name.
Query the API to find the latest Debian image to deploy the base system with.
* gnu/machine/hetzner/http.scm (null-or): New procedure.
(<hetzner-image>): New JSON record type.
(<hetzner-image-created-from>): Likewise.
(<hetzner-image-protection>): Likewise.
(%hetzner-default-server-image): Change simple variable to a memoized
procedure.
(hetzner-api-server-create): Adjust user accordingly.
(hetzner-api-images): New procedure.
Change-Id: I9544708c878971a2c776c80b9a4ee06078d5ce61
Diffstat (limited to 'gnu')
| -rw-r--r-- | gnu/machine/hetzner/http.scm | 79 |
1 files changed, 77 insertions, 2 deletions
diff --git a/gnu/machine/hetzner/http.scm b/gnu/machine/hetzner/http.scm index 4f81b27ca92..f8580021a9e 100644 --- a/gnu/machine/hetzner/http.scm +++ b/gnu/machine/hetzner/http.scm | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | ;;; GNU Guix --- Functional package management for GNU | 1 | ;;; GNU Guix --- Functional package management for GNU |
| 2 | ;;; Copyright © 2024 Roman Scherer <roman@burningswell.com> | 2 | ;;; Copyright © 2024 Roman Scherer <roman@burningswell.com> |
| 3 | ;;; Copyright © 2026 Maxim Cournoyer <maxim@guixotic.coop> | ||
| 3 | ;;; | 4 | ;;; |
| 4 | ;;; This file is part of GNU Guix. | 5 | ;;; This file is part of GNU Guix. |
| 5 | ;;; | 6 | ;;; |
| @@ -19,6 +20,7 @@ | |||
| 19 | (define-module (gnu machine hetzner http) | 20 | (define-module (gnu machine hetzner http) |
| 20 | #:use-module (guix diagnostics) | 21 | #:use-module (guix diagnostics) |
| 21 | #:use-module (guix i18n) | 22 | #:use-module (guix i18n) |
| 23 | #:use-module (guix memoization) | ||
| 22 | #:use-module (guix records) | 24 | #:use-module (guix records) |
| 23 | #:use-module (ice-9 iconv) | 25 | #:use-module (ice-9 iconv) |
| 24 | #:use-module (ice-9 match) | 26 | #:use-module (ice-9 match) |
| @@ -51,6 +53,7 @@ | |||
| 51 | hetzner-api-action-wait | 53 | hetzner-api-action-wait |
| 52 | hetzner-api-actions | 54 | hetzner-api-actions |
| 53 | hetzner-api-create-ssh-key | 55 | hetzner-api-create-ssh-key |
| 56 | hetzner-api-images | ||
| 54 | hetzner-api-locations | 57 | hetzner-api-locations |
| 55 | hetzner-api-primary-ips | 58 | hetzner-api-primary-ips |
| 56 | hetzner-api-request-body | 59 | hetzner-api-request-body |
| @@ -81,6 +84,23 @@ | |||
| 81 | hetzner-error-code | 84 | hetzner-error-code |
| 82 | hetzner-error-message | 85 | hetzner-error-message |
| 83 | hetzner-error? | 86 | hetzner-error? |
| 87 | hetzner-image? | ||
| 88 | hetzner-image-id | ||
| 89 | hetzner-image-type | ||
| 90 | hetzner-image-status | ||
| 91 | hetzner-image-name | ||
| 92 | hetzner-image-description | ||
| 93 | hetzner-image-disk-size | ||
| 94 | hetzner-image-created | ||
| 95 | hetzner-image-created-from | ||
| 96 | hetzner-image-bound-to | ||
| 97 | hetzner-image-os-flavor | ||
| 98 | hetzner-image-os-version | ||
| 99 | hetzner-image-rapid-deploy | ||
| 100 | hetzner-image-protection | ||
| 101 | hetzner-image-deprecated | ||
| 102 | hetzner-image-deleted | ||
| 103 | hetzner-image-architecture | ||
| 84 | hetzner-ipv4-blocked? | 104 | hetzner-ipv4-blocked? |
| 85 | hetzner-ipv4-dns-ptr | 105 | hetzner-ipv4-dns-ptr |
| 86 | hetzner-ipv4-id | 106 | hetzner-ipv4-id |
| @@ -148,6 +168,7 @@ | |||
| 148 | hetzner-ssh-key? | 168 | hetzner-ssh-key? |
| 149 | make-hetzner-action | 169 | make-hetzner-action |
| 150 | make-hetzner-error | 170 | make-hetzner-error |
| 171 | make-hetzner-image | ||
| 151 | make-hetzner-ipv4 | 172 | make-hetzner-ipv4 |
| 152 | make-hetzner-ipv6 | 173 | make-hetzner-ipv6 |
| 153 | make-hetzner-location | 174 | make-hetzner-location |
| @@ -168,7 +189,19 @@ | |||
| 168 | (make-parameter (getenv "GUIX_HETZNER_API_TOKEN"))) | 189 | (make-parameter (getenv "GUIX_HETZNER_API_TOKEN"))) |
| 169 | 190 | ||
| 170 | ;; Ideally this would be a Guix image. Maybe one day. | 191 | ;; Ideally this would be a Guix image. Maybe one day. |
| 171 | (define %hetzner-default-server-image "debian-11") | 192 | (define %hetzner-default-server-image |
| 193 | (mlambda (api) | ||
| 194 | "Return the latest Debian image available. This image gets used for the | ||
| 195 | initial system provisioning phase, before Guix System takes over." | ||
| 196 | (let ((debian-images (filter (lambda (image) | ||
| 197 | (string=? "debian" | ||
| 198 | (hetzner-image-os-flavor image))) | ||
| 199 | (hetzner-api-images api)))) | ||
| 200 | (hetzner-image-name | ||
| 201 | (last (sort debian-images | ||
| 202 | (lambda (x y) | ||
| 203 | (< (string->number (hetzner-image-os-version x)) | ||
| 204 | (string->number (hetzner-image-os-version y)))))))))) | ||
| 172 | 205 | ||
| 173 | ;; Falkenstein, Germany | 206 | ;; Falkenstein, Germany |
| 174 | (define %hetzner-default-server-location "fsn1") | 207 | (define %hetzner-default-server-location "fsn1") |
| @@ -290,6 +323,43 @@ | |||
| 290 | (server-type hetzner-server-type "server_type" | 323 | (server-type hetzner-server-type "server_type" |
| 291 | json->hetzner-server-type)) ; <hetzner-server-type> | 324 | json->hetzner-server-type)) ; <hetzner-server-type> |
| 292 | 325 | ||
| 326 | (define-json-mapping <hetzner-image> | ||
| 327 | make-hetzner-image hetzner-image? json->hetzner-image | ||
| 328 | (id hetzner-image-id) ;integer | ||
| 329 | (type hetzner-image-type) ;string | ||
| 330 | (status hetzner-image-status) ;string | ||
| 331 | (name hetzner-image-name "name" (null-or identity)) ;string | null | ||
| 332 | (description hetzner-image-description) ;string | ||
| 333 | (image-size hetzner-image-size "image_size" ;number | null (GiB) | ||
| 334 | (null-or identity)) | ||
| 335 | (disk-size hetzner-image-disk-size "disk_size") ;number (GiB) | ||
| 336 | (created hetzner-image-created) ;string (date) | ||
| 337 | (created-from hetzner-image-created-from "created_from" ;object | null | ||
| 338 | (null-or json->hetzner-image-created-from)) | ||
| 339 | (bound-to hetzner-image-bound-to "bound_to" (null-or identity)) ;integer | null | ||
| 340 | (os-flavor hetzner-image-os-flavor "os_flavor") ;string | ||
| 341 | (os-version hetzner-image-os-version "os_version" ;string | null | ||
| 342 | (null-or identity)) | ||
| 343 | (rapid-deploy hetzner-image-rapid-deploy "rapid_deploy") ;boolean | ||
| 344 | (protection hetzner-image-protection "protection" ;object | ||
| 345 | json->hetzner-image-protection) | ||
| 346 | (deprecated hetzner-image-deprecated) ;string | ||
| 347 | (deleted hetzner-image-deleted "deleted" (null-or identity)) ;null | string | ||
| 348 | (architecture hetzner-image-architecture)) ;string | ||
| 349 | |||
| 350 | (define (null-or parser) | ||
| 351 | (lambda (value) | ||
| 352 | (if (eq? 'null value) | ||
| 353 | *unspecified* | ||
| 354 | (parser value)))) | ||
| 355 | |||
| 356 | (define-json-type <hetzner-image-created-from> | ||
| 357 | (id) ;integer | ||
| 358 | (name)) ;string | ||
| 359 | |||
| 360 | (define-json-type <hetzner-image-protection> | ||
| 361 | (delete)) ;boolean | ||
| 362 | |||
| 293 | (define-json-mapping <hetzner-server-type> | 363 | (define-json-mapping <hetzner-server-type> |
| 294 | make-hetzner-server-type hetzner-server-type? json->hetzner-server-type | 364 | make-hetzner-server-type hetzner-server-type? json->hetzner-server-type |
| 295 | (architecture hetzner-server-type-architecture) ; string | 365 | (architecture hetzner-server-type-architecture) ; string |
| @@ -602,7 +672,7 @@ | |||
| 602 | ssh-keys | 672 | ssh-keys |
| 603 | (ipv4 #f) | 673 | (ipv4 #f) |
| 604 | (ipv6 #f) | 674 | (ipv6 #f) |
| 605 | (image %hetzner-default-server-image) | 675 | (image (%hetzner-default-server-image api)) |
| 606 | (labels '()) | 676 | (labels '()) |
| 607 | (location %hetzner-default-server-location) | 677 | (location %hetzner-default-server-location) |
| 608 | (server-type %hetzner-default-server-type) | 678 | (server-type %hetzner-default-server-type) |
| @@ -694,3 +764,8 @@ | |||
| 694 | "Get server types from the Hetzner API." | 764 | "Get server types from the Hetzner API." |
| 695 | (apply hetzner-api-list api "/server_types" "server_types" | 765 | (apply hetzner-api-list api "/server_types" "server_types" |
| 696 | json->hetzner-server-type options)) | 766 | json->hetzner-server-type options)) |
| 767 | |||
| 768 | (define* (hetzner-api-images api . options) | ||
| 769 | "Get image types from the Hetzner API." | ||
| 770 | (apply hetzner-api-list api "/images" "images" | ||
| 771 | json->hetzner-image options)) | ||
