| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
| 10 | |
| 11 | |
| 12 | |
| 13 | |
| 14 | |
| 15 | |
| 16 | |
| 17 | |
| 18 | |
| 19 |
|
| 20 | (define-module (tests machine hetzner http)
|
| 21 | #:use-module (gnu machine hetzner http)
|
| 22 | #:use-module (guix build utils)
|
| 23 | #:use-module (guix tests)
|
| 24 | #:use-module (srfi srfi-1)
|
| 25 | #:use-module (srfi srfi-34)
|
| 26 | #:use-module (srfi srfi-64)
|
| 27 | #:use-module (ssh key)
|
| 28 | #:use-module (ice-9 match))
|
| 29 |
|
| 30 | |
| 31 |
|
| 32 | |
| 33 | |
| 34 |
|
| 35 | |
| 36 | |
| 37 |
|
| 38 | (define %labels
|
| 39 | '(("guix.gnu.org/test" . "true")))
|
| 40 |
|
| 41 | (define %server-name
|
| 42 | "guix-hetzner-api-test-server")
|
| 43 |
|
| 44 | (define %ssh-key-name
|
| 45 | "guix-hetzner-api-test-key")
|
| 46 |
|
| 47 | (define %ssh-key-file
|
| 48 | (string-append "/tmp/" %ssh-key-name))
|
| 49 |
|
| 50 | (unless (file-exists? %ssh-key-file)
|
| 51 | (private-key-to-file (make-keypair 'rsa 2048) %ssh-key-file))
|
| 52 |
|
| 53 | (define %ssh-key
|
| 54 | (hetzner-ssh-key-read-file %ssh-key-file))
|
| 55 |
|
| 56 | (define %when-no-token
|
| 57 | (if (hetzner-api-token (hetzner-api)) 0 1))
|
| 58 |
|
| 59 | (define action-create-server
|
| 60 | (make-hetzner-action
|
| 61 | "create_server" #f *unspecified* 1896091819 0
|
| 62 | (list (make-hetzner-resource 59570198 "server"))
|
| 63 | #(0 17 11 2 1 125 0 32 -1 0 #f) "running"))
|
| 64 |
|
| 65 | (define action-create-server-alist
|
| 66 | '(("command" . "create_server")
|
| 67 | ("error" . null)
|
| 68 | ("finished" . null)
|
| 69 | ("id" . 1896091819)
|
| 70 | ("progress" . 0)
|
| 71 | ("resources" . #((("type" . "server") ("id" . 59570198))))
|
| 72 | ("started" . "2025-02-02T11:17:00+00:00")
|
| 73 | ("status" . "running")))
|
| 74 |
|
| 75 | (define action-delete-server
|
| 76 | (make-hetzner-action
|
| 77 | "delete_server" #f *unspecified* 1896091928 0
|
| 78 | (list (make-hetzner-resource 59570198 "server"))
|
| 79 | #(10 17 11 2 1 125 0 32 -1 0 #f) "running"))
|
| 80 |
|
| 81 | (define action-delete-server-alist
|
| 82 | '(("command" . "delete_server")
|
| 83 | ("error" . null)
|
| 84 | ("finished" . null)
|
| 85 | ("id" . 1896091928)
|
| 86 | ("progress" . 0)
|
| 87 | ("resources" . #((("type" . "server") ("id" . 59570198))))
|
| 88 | ("started" . "2025-02-02T11:17:10+00:00")
|
| 89 | ("status" . "running")))
|
| 90 |
|
| 91 | (define action-enable-rescue
|
| 92 | (make-hetzner-action
|
| 93 | "enable_rescue" #f *unspecified* 1896091721 0
|
| 94 | (list (make-hetzner-resource 59570198 "server"))
|
| 95 | #(10 17 11 2 1 125 0 32 -1 0 #f) "success"))
|
| 96 |
|
| 97 | (define action-enable-rescue-alist
|
| 98 | '(("command" . "enable_rescue")
|
| 99 | ("error" . null)
|
| 100 | ("finished" . null)
|
| 101 | ("id" . 1896091721)
|
| 102 | ("progress" . 0)
|
| 103 | ("resources" . #((("type" . "server") ("id" . 59570198))))
|
| 104 | ("started" . "2025-02-02T11:17:10+00:00")
|
| 105 | ("status" . "running")))
|
| 106 |
|
| 107 | (define action-power-off
|
| 108 | (make-hetzner-action
|
| 109 | "stop_server" #f *unspecified* 1896091721 0
|
| 110 | (list (make-hetzner-resource 59570198 "server"))
|
| 111 | #(10 17 11 2 1 125 0 32 -1 0 #f) "success"))
|
| 112 |
|
| 113 | (define action-power-off-alist
|
| 114 | '(("command" . "stop_server")
|
| 115 | ("error" . null)
|
| 116 | ("finished" . null)
|
| 117 | ("id" . 1896091721)
|
| 118 | ("progress" . 0)
|
| 119 | ("resources" . #((("type" . "server") ("id" . 59570198))))
|
| 120 | ("started" . "2025-02-02T11:17:10+00:00")
|
| 121 | ("status" . "running")))
|
| 122 |
|
| 123 | (define action-power-on
|
| 124 | (make-hetzner-action
|
| 125 | "start_server" #f *unspecified* 1896091721 0
|
| 126 | (list (make-hetzner-resource 59570198 "server"))
|
| 127 | #(10 17 11 2 1 125 0 32 -1 0 #f) "success"))
|
| 128 |
|
| 129 | (define action-power-on-alist
|
| 130 | '(("command" . "start_server")
|
| 131 | ("error" . null)
|
| 132 | ("finished" . null)
|
| 133 | ("id" . 1896091721)
|
| 134 | ("progress" . 0)
|
| 135 | ("resources" . #((("type" . "server") ("id" . 59570198))))
|
| 136 | ("started" . "2025-02-02T11:17:10+00:00")
|
| 137 | ("status" . "running")))
|
| 138 |
|
| 139 | (define action-reboot
|
| 140 | (make-hetzner-action
|
| 141 | "reboot_server" #f *unspecified* 1896091721 0
|
| 142 | (list (make-hetzner-resource 59570198 "server"))
|
| 143 | #(10 17 11 2 1 125 0 32 -1 0 #f) "success"))
|
| 144 |
|
| 145 | (define action-reboot-alist
|
| 146 | '(("command" . "reboot_server")
|
| 147 | ("error" . null)
|
| 148 | ("finished" . null)
|
| 149 | ("id" . 1896091721)
|
| 150 | ("progress" . 0)
|
| 151 | ("resources" . #((("type" . "server") ("id" . 59570198))))
|
| 152 | ("started" . "2025-02-02T11:17:10+00:00")
|
| 153 | ("status" . "running")))
|
| 154 |
|
| 155 | (define meta-page-alist
|
| 156 | '("pagination"
|
| 157 | ("last_page" . 1)
|
| 158 | ("next_page" . null)
|
| 159 | ("page" . 1)
|
| 160 | ("per_page" . 25)
|
| 161 | ("previous_page" . null)
|
| 162 | ("total_entries" . 1)))
|
| 163 |
|
| 164 | (define location-falkenstein
|
| 165 | (make-hetzner-location
|
| 166 | "Falkenstein" "DE" "Falkenstein DC Park 1"
|
| 167 | 1 50.47612 12.370071 "fsn1" "eu-central"))
|
| 168 |
|
| 169 | (define location-falkenstein-alist
|
| 170 | `(("city" . "Falkenstein")
|
| 171 | ("country" . "DE")
|
| 172 | ("description" . "Falkenstein DC Park 1")
|
| 173 | ("id" . 1)
|
| 174 | ("latitude" . 50.47612)
|
| 175 | ("longitude" . 12.370071)
|
| 176 | ("name" . "fsn1")
|
| 177 | ("network_zone" . "eu-central")))
|
| 178 |
|
| 179 | (define server-type-cpx-11
|
| 180 | (make-hetzner-server-type
|
| 181 | "x86" 2 "shared" #f *unspecified*
|
| 182 | "CPX 11" 40 22 2 "cpx11" "local"))
|
| 183 |
|
| 184 | (define server-type-cpx-11-alist
|
| 185 | `(("architecture" . "x86")
|
| 186 | ("cores" . 2)
|
| 187 | ("cpu_type" . "shared")
|
| 188 | ("deprecated" . #f)
|
| 189 | ("deprecation" . null)
|
| 190 | ("description" . "CPX 11")
|
| 191 | ("disk" . 40)
|
| 192 | ("id" . 22)
|
| 193 | ("memory" . 2)
|
| 194 | ("name" . "cpx11")
|
| 195 | ("storage_type" . "local")))
|
| 196 |
|
| 197 | (define server-x86
|
| 198 | (make-hetzner-server
|
| 199 | "2024-12-30T16:38:11+00:00"
|
| 200 | 59570198
|
| 201 | '()
|
| 202 | "guix-x86"
|
| 203 | (make-hetzner-public-net
|
| 204 | (make-hetzner-ipv4 #f "static.218.128.13.49.clients.your-server.de" 78014457 "49.13.128.218")
|
| 205 | (make-hetzner-ipv6 #f '() 78014458 "2a01:4f8:c17:293e::/64"))
|
| 206 | #f
|
| 207 | server-type-cpx-11))
|
| 208 |
|
| 209 | (define server-x86-alist
|
| 210 | `(("backup_window" . null)
|
| 211 | ("created" . "2024-12-30T16:38:11+00:00")
|
| 212 | ("id" . 59570198)
|
| 213 | ("included_traffic" . 21990232555520)
|
| 214 | ("ingoing_traffic" . 124530000)
|
| 215 | ("iso" . null)
|
| 216 | ("labels")
|
| 217 | ("load_balancers" . #())
|
| 218 | ("locked" . #f)
|
| 219 | ("name" . "guix-x86")
|
| 220 | ("outgoing_traffic" . 1391250000)
|
| 221 | ("placement_group" . null)
|
| 222 | ("primary_disk_size" . 320)
|
| 223 | ("private_net" . #())
|
| 224 | ("protection" ("rebuild" . #f) ("delete" . #f))
|
| 225 | ("public_net"
|
| 226 | ("firewalls" . #())
|
| 227 | ("floating_ips" . #())
|
| 228 | ("ipv6"
|
| 229 | ("id" . 78014458)
|
| 230 | ("dns_ptr" . #())
|
| 231 | ("blocked" . #f)
|
| 232 | ("ip" . "2a01:4f8:c17:293e::/64"))
|
| 233 | ("ipv4"
|
| 234 | ("id" . 78014457)
|
| 235 | ("dns_ptr" . "static.218.128.13.49.clients.your-server.de")
|
| 236 | ("blocked" . #f)
|
| 237 | ("ip" . "49.13.128.218")))
|
| 238 | ("rescue_enabled" . #f)
|
| 239 | ("server_type" ,@server-type-cpx-11-alist)
|
| 240 | ("status" . "running")
|
| 241 | ("volumes" . #())))
|
| 242 |
|
| 243 | (define primary-ip
|
| 244 | (make-hetzner-primary-ip
|
| 245 | #(55 2 19 28 9 123 6 300 -1 0 #f)
|
| 246 | 42
|
| 247 | "131.232.99.1"
|
| 248 | '()
|
| 249 | "static-ip"
|
| 250 | "ipv4"))
|
| 251 |
|
| 252 | (define primary-ip-alist
|
| 253 | `(("created" . "2023-10-28T19:02:55+00:00")
|
| 254 | ("id" . 42)
|
| 255 | ("labels")
|
| 256 | ("name" . "static-ip")
|
| 257 | ("blocked" . #f)
|
| 258 | ("ip" . "131.232.99.1")
|
| 259 | ("datacenter")
|
| 260 | ("dns_ptr")
|
| 261 | ("protection" . (("delete" . #f)))
|
| 262 | ("type" . "ipv4")
|
| 263 | ("auto_delete" . #t)
|
| 264 | ("assignee_type" . "server")
|
| 265 | ("assignee_id" . 17)))
|
| 266 |
|
| 267 | (define ssh-key-root
|
| 268 | (make-hetzner-ssh-key
|
| 269 | #(55 2 19 28 9 123 6 300 -1 0 #f)
|
| 270 | "8c:25:09:8f:37:0f:d8:f0:99:4e:ab:c7:5c:1b:c6:53"
|
| 271 | 16510983 '() "[email protected]"
|
| 272 | "ssh-ed25519 ABCAC3NzaC1lZDI1NTE5AAAAIBT3lLYPfOZV9NNrNk0jGCufWmXbFSz+ORxowJdHoSIM"))
|
| 273 |
|
| 274 | (define ssh-key-root-alist
|
| 275 | `(("created" . "2023-10-28T19:02:55+00:00")
|
| 276 | ("fingerprint" . "8c:25:09:8f:37:0f:d8:f0:99:4e:ab:c7:5c:1b:c6:53")
|
| 277 | ("id" . 16510983)
|
| 278 | ("labels")
|
| 279 | ("name" . "[email protected]")
|
| 280 | ("public_key" . "ssh-ed25519 ABCAC3NzaC1lZDI1NTE5AAAAIBT3lLYPfOZV9NNrNk0jGCufWmXbFSz+ORxowJdHoSIM")))
|
| 281 |
|
| 282 | (define* (create-ssh-key api ssh-key #:key (labels %labels))
|
| 283 | (hetzner-api-ssh-key-create
|
| 284 | api
|
| 285 | (hetzner-ssh-key-name ssh-key)
|
| 286 | (hetzner-ssh-key-public-key ssh-key)
|
| 287 | #:labels labels))
|
| 288 |
|
| 289 | (define* (create-server api ssh-key #:key (labels %labels))
|
| 290 | (hetzner-api-server-create api %server-name
|
| 291 | #:ssh-keys (list ssh-key)
|
| 292 | #:labels labels
|
| 293 | #:server-type "cpx31"))
|
| 294 |
|
| 295 | (define (cleanup api)
|
| 296 | (for-each (lambda (server)
|
| 297 | (hetzner-api-server-delete api server))
|
| 298 | (hetzner-api-servers
|
| 299 | api #:params `(("label_selector" . "guix.gnu.org/test=true"))))
|
| 300 | (for-each (lambda (ssh-key)
|
| 301 | (hetzner-api-ssh-key-delete api ssh-key))
|
| 302 | (hetzner-api-ssh-keys
|
| 303 | api #:params `(("label_selector" . "guix.gnu.org/test=true"))))
|
| 304 | api)
|
| 305 |
|
| 306 | (define-syntax-rule (with-cleanup-api (api-sym api-init) body ...)
|
| 307 | (let ((api-sym (cleanup api-init)))
|
| 308 | (dynamic-wind
|
| 309 | (const #t)
|
| 310 | (lambda ()
|
| 311 | body ...)
|
| 312 | (lambda ()
|
| 313 | (cleanup api-sym)))))
|
| 314 |
|
| 315 | (test-begin "machine-hetzner-api")
|
| 316 |
|
| 317 | |
| 318 |
|
| 319 | (test-equal "hetzner-api-actions-unit"
|
| 320 | (list action-create-server action-delete-server)
|
| 321 | (let ((actions (list action-create-server-alist action-delete-server-alist)))
|
| 322 | (mock ((gnu machine hetzner http) hetzner-api-request-send
|
| 323 | (lambda* (request #:key expected)
|
| 324 | (match (list (hetzner-api-request-method request)
|
| 325 | (hetzner-api-request-url request))
|
| 326 | (('GET "https://api.hetzner.cloud/v1/actions")
|
| 327 | (and (unspecified? (hetzner-api-request-body request))
|
| 328 | (equal? `(("page" . 1)
|
| 329 | ("id" . ,(string-join
|
| 330 | (map (lambda (action)
|
| 331 | (number->string (assoc-ref action "id")))
|
| 332 | actions)
|
| 333 | ",")))
|
| 334 | (hetzner-api-request-params request))
|
| 335 | (hetzner-api-response
|
| 336 | (body `(("meta" . ,meta-page-alist)
|
| 337 | ("actions" . #(,action-create-server-alist
|
| 338 | ,action-delete-server-alist))))))))))
|
| 339 | (hetzner-api-actions (hetzner-api)
|
| 340 | (map (lambda (action)
|
| 341 | (assoc-ref action "id"))
|
| 342 | actions)))))
|
| 343 |
|
| 344 | (test-equal "hetzner-api-locations-unit"
|
| 345 | (list location-falkenstein)
|
| 346 | (mock ((gnu machine hetzner http) hetzner-api-request-send
|
| 347 | (lambda* (request #:key expected)
|
| 348 | (match (list (hetzner-api-request-method request)
|
| 349 | (hetzner-api-request-url request))
|
| 350 | (('GET "https://api.hetzner.cloud/v1/locations")
|
| 351 | (and (unspecified? (hetzner-api-request-body request))
|
| 352 | (equal? '(("page" . 1))
|
| 353 | (hetzner-api-request-params request))
|
| 354 | (hetzner-api-response
|
| 355 | (body `(("meta" . ,meta-page-alist)
|
| 356 | ("locations" . #(,location-falkenstein-alist))))))))))
|
| 357 | (hetzner-api-locations (hetzner-api))))
|
| 358 |
|
| 359 | (test-equal "hetzner-api-server-types-unit"
|
| 360 | (list server-type-cpx-11)
|
| 361 | (mock ((gnu machine hetzner http) hetzner-api-request-send
|
| 362 | (lambda* (request #:key expected)
|
| 363 | (match (list (hetzner-api-request-method request)
|
| 364 | (hetzner-api-request-url request))
|
| 365 | (('GET "https://api.hetzner.cloud/v1/server_types")
|
| 366 | (and (unspecified? (hetzner-api-request-body request))
|
| 367 | (equal? '(("page" . 1))
|
| 368 | (hetzner-api-request-params request))
|
| 369 | (hetzner-api-response
|
| 370 | (body `(("meta" . ,meta-page-alist)
|
| 371 | ("server_types" . #(,server-type-cpx-11-alist))))))))))
|
| 372 | (hetzner-api-server-types (hetzner-api))))
|
| 373 |
|
| 374 | (test-equal "hetzner-api-server-create-unit"
|
| 375 | server-x86
|
| 376 | (mock ((gnu machine hetzner http) hetzner-api-request-send
|
| 377 | (lambda* (request #:key expected)
|
| 378 | (match (list (hetzner-api-request-method request)
|
| 379 | (hetzner-api-request-url request))
|
| 380 | (('GET "https://api.hetzner.cloud/v1/images")
|
| 381 | (hetzner-api-response
|
| 382 | (body `(("images"
|
| 383 | . #((("id" . 123)
|
| 384 | ("created_from" . null)
|
| 385 | ("protection" . (("delete" . #t)))
|
| 386 | ("os_flavor" . "debian"))))))))
|
| 387 | (('POST "https://api.hetzner.cloud/v1/servers")
|
| 388 | (hetzner-api-response
|
| 389 | (body `(("action" . ,action-create-server-alist)
|
| 390 | ("server" . ,server-x86-alist)))))
|
| 391 | (('GET "https://api.hetzner.cloud/v1/actions")
|
| 392 | (hetzner-api-response
|
| 393 | (body `(("actions" . ,(vector (cons `("status" . "success")
|
| 394 | action-create-server-alist)))
|
| 395 | ("meta" . ,meta-page-alist))))))))
|
| 396 | (hetzner-api-server-create (hetzner-api) %server-name
|
| 397 | #:ssh-keys (list ssh-key-root))))
|
| 398 |
|
| 399 | (test-equal "hetzner-api-server-delete-unit"
|
| 400 | (make-hetzner-action
|
| 401 | "delete_server" #f *unspecified* 1896091928 0
|
| 402 | (list (make-hetzner-resource 59570198 "server"))
|
| 403 | #(10 17 11 2 1 125 0 32 -1 0 #f) "success")
|
| 404 | (mock ((gnu machine hetzner http) hetzner-api-request-send
|
| 405 | (lambda* (request #:key expected)
|
| 406 | (match (list (hetzner-api-request-method request)
|
| 407 | (hetzner-api-request-url request))
|
| 408 | (('DELETE "https://api.hetzner.cloud/v1/servers/59570198")
|
| 409 | (hetzner-api-response
|
| 410 | (body `(("action" . ,action-delete-server-alist)))))
|
| 411 | (('GET "https://api.hetzner.cloud/v1/actions")
|
| 412 | (hetzner-api-response
|
| 413 | (body `(("actions" . ,(vector (cons `("status" . "success")
|
| 414 | action-delete-server-alist)))
|
| 415 | ("meta" . ,meta-page-alist))))))))
|
| 416 | (hetzner-api-server-delete (hetzner-api) server-x86)))
|
| 417 |
|
| 418 | (test-equal "hetzner-api-server-enable-rescue-system-unit"
|
| 419 | action-enable-rescue
|
| 420 | (mock ((gnu machine hetzner http) hetzner-api-request-send
|
| 421 | (lambda* (request #:key expected)
|
| 422 | (match (list (hetzner-api-request-method request)
|
| 423 | (hetzner-api-request-url request))
|
| 424 | (('POST
|
| 425 | "https://api.hetzner.cloud/v1/servers/59570198/actions/enable_rescue")
|
| 426 | (hetzner-api-response
|
| 427 | (body `(("action" . ,action-enable-rescue-alist)))))
|
| 428 | (('GET "https://api.hetzner.cloud/v1/actions")
|
| 429 | (hetzner-api-response
|
| 430 | (body `(("actions" . ,(vector (cons `("status" . "success")
|
| 431 | action-enable-rescue-alist)))
|
| 432 | ("meta" . ,meta-page-alist))))))))
|
| 433 | (hetzner-api-server-enable-rescue-system
|
| 434 | (hetzner-api) server-x86 #:ssh-keys (list ssh-key-root))))
|
| 435 |
|
| 436 | (test-equal "hetzner-api-server-power-on-unit"
|
| 437 | action-power-on
|
| 438 | (mock ((gnu machine hetzner http) hetzner-api-request-send
|
| 439 | (lambda* (request #:key expected)
|
| 440 | (match (list (hetzner-api-request-method request)
|
| 441 | (hetzner-api-request-url request))
|
| 442 | (('POST
|
| 443 | "https://api.hetzner.cloud/v1/servers/59570198/actions/poweron")
|
| 444 | (hetzner-api-response
|
| 445 | (body `(("action" . ,action-power-on-alist)))))
|
| 446 | (('GET "https://api.hetzner.cloud/v1/actions")
|
| 447 | (hetzner-api-response
|
| 448 | (body `(("actions" . ,(vector (cons `("status" . "success")
|
| 449 | action-power-on-alist)))
|
| 450 | ("meta" . ,meta-page-alist))))))))
|
| 451 | (hetzner-api-server-power-on (hetzner-api) server-x86)))
|
| 452 |
|
| 453 | (test-equal "hetzner-api-server-power-off-unit"
|
| 454 | action-power-off
|
| 455 | (mock ((gnu machine hetzner http) hetzner-api-request-send
|
| 456 | (lambda* (request #:key expected)
|
| 457 | (match (list (hetzner-api-request-method request)
|
| 458 | (hetzner-api-request-url request))
|
| 459 | (('POST
|
| 460 | "https://api.hetzner.cloud/v1/servers/59570198/actions/poweroff")
|
| 461 | (hetzner-api-response
|
| 462 | (body `(("action" . ,action-power-off-alist)))))
|
| 463 | (('GET "https://api.hetzner.cloud/v1/actions")
|
| 464 | (hetzner-api-response
|
| 465 | (body `(("actions" . ,(vector (cons `("status" . "success")
|
| 466 | action-power-off-alist)))
|
| 467 | ("meta" . ,meta-page-alist))))))))
|
| 468 | (hetzner-api-server-power-off (hetzner-api) server-x86)))
|
| 469 |
|
| 470 | (test-equal "hetzner-api-server-reboot-unit"
|
| 471 | action-reboot
|
| 472 | (mock ((gnu machine hetzner http) hetzner-api-request-send
|
| 473 | (lambda* (request #:key expected)
|
| 474 | (match (list (hetzner-api-request-method request)
|
| 475 | (hetzner-api-request-url request))
|
| 476 | (('POST
|
| 477 | "https://api.hetzner.cloud/v1/servers/59570198/actions/reboot")
|
| 478 | (hetzner-api-response
|
| 479 | (body `(("action" . ,action-reboot-alist)))))
|
| 480 | (('GET "https://api.hetzner.cloud/v1/actions")
|
| 481 | (hetzner-api-response
|
| 482 | (body `(("actions" . ,(vector (cons `("status" . "success")
|
| 483 | action-reboot-alist)))
|
| 484 | ("meta" . ,meta-page-alist))))))))
|
| 485 | (hetzner-api-server-reboot (hetzner-api) server-x86)))
|
| 486 |
|
| 487 | (test-equal "hetzner-api-servers-unit"
|
| 488 | (list server-x86)
|
| 489 | (mock ((gnu machine hetzner http) hetzner-api-request-send
|
| 490 | (lambda* (request #:key expected)
|
| 491 | (hetzner-api-response
|
| 492 | (body `(("meta" . ,meta-page-alist)
|
| 493 | ("servers" . #(,server-x86-alist)))))))
|
| 494 | (hetzner-api-servers (hetzner-api))))
|
| 495 |
|
| 496 | (test-equal "hetzner-api-ssh-key-create-unit"
|
| 497 | ssh-key-root
|
| 498 | (mock ((gnu machine hetzner http) hetzner-api-request-send
|
| 499 | (lambda* (request #:key expected)
|
| 500 | (match (list (hetzner-api-request-method request)
|
| 501 | (hetzner-api-request-url request))
|
| 502 | (('POST "https://api.hetzner.cloud/v1/ssh_keys")
|
| 503 | (and (equal? `(("name" . "guix-hetzner-api-test-key")
|
| 504 | ("public_key" . "ssh-ed25519 ABCAC3NzaC1lZDI1NTE5AAAAIBT3lLYPfOZV9NNrNk0jGCufWmXbFSz+ORxowJdHoSIM")
|
| 505 | ("labels" . (("a" . "1"))))
|
| 506 | (hetzner-api-request-body request))
|
| 507 | (null? (hetzner-api-request-params request))
|
| 508 | (hetzner-api-response
|
| 509 | (body `(("ssh_key" . ,ssh-key-root-alist)))))))))
|
| 510 | (hetzner-api-ssh-key-create
|
| 511 | (hetzner-api)
|
| 512 | "guix-hetzner-api-test-key"
|
| 513 | "ssh-ed25519 ABCAC3NzaC1lZDI1NTE5AAAAIBT3lLYPfOZV9NNrNk0jGCufWmXbFSz+ORxowJdHoSIM"
|
| 514 | #:labels '(("a" . "1")))))
|
| 515 |
|
| 516 | (test-assert "hetzner-api-ssh-key-delete-unit"
|
| 517 | (mock ((gnu machine hetzner http) hetzner-api-request-send
|
| 518 | (lambda* (request #:key expected)
|
| 519 | (match (list (hetzner-api-request-method request)
|
| 520 | (hetzner-api-request-url request))
|
| 521 | (('DELETE "https://api.hetzner.cloud/v1/ssh_keys/16510983")
|
| 522 | (hetzner-api-response)))))
|
| 523 | (hetzner-api-ssh-key-delete (hetzner-api) ssh-key-root)))
|
| 524 |
|
| 525 | (test-equal "hetzner-api-ssh-keys-unit"
|
| 526 | (list ssh-key-root)
|
| 527 | (mock ((gnu machine hetzner http) hetzner-api-request-send
|
| 528 | (lambda* (request #:key expected)
|
| 529 | (match (list (hetzner-api-request-method request)
|
| 530 | (hetzner-api-request-url request))
|
| 531 | (('GET "https://api.hetzner.cloud/v1/ssh_keys")
|
| 532 | (and (unspecified? (hetzner-api-request-body request))
|
| 533 | (equal? '(("page" . 1))
|
| 534 | (hetzner-api-request-params request))
|
| 535 | (hetzner-api-response
|
| 536 | (body `(("meta" . ,meta-page-alist)
|
| 537 | ("ssh_keys" . #(,ssh-key-root-alist))))))))))
|
| 538 | (hetzner-api-ssh-keys (hetzner-api))))
|
| 539 |
|
| 540 | (test-equal "hetzner-api-primary-ips-unit"
|
| 541 | (list primary-ip)
|
| 542 | (mock ((gnu machine hetzner http) hetzner-api-request-send
|
| 543 | (lambda* (request #:key expected)
|
| 544 | (match (list (hetzner-api-request-method request)
|
| 545 | (hetzner-api-request-url request))
|
| 546 | (('GET "https://api.hetzner.cloud/v1/primary_ips")
|
| 547 | (and (unspecified? (hetzner-api-request-body request))
|
| 548 | (equal? '(("page" . 1))
|
| 549 | (hetzner-api-request-params request))
|
| 550 | (hetzner-api-response
|
| 551 | (body `(("meta" . ,meta-page-alist)
|
| 552 | ("primary_ips" . #(,primary-ip-alist))))))))))
|
| 553 | (hetzner-api-primary-ips (hetzner-api))))
|
| 554 |
|
| 555 | |
| 556 |
|
| 557 | (test-skip %when-no-token)
|
| 558 | (test-assert "hetzner-api-actions-integration"
|
| 559 | (with-cleanup-api (api (hetzner-api))
|
| 560 | (let* ((ssh-key (create-ssh-key api %ssh-key))
|
| 561 | (server (create-server api ssh-key))
|
| 562 | (action (hetzner-api-server-enable-rescue-system
|
| 563 | api server #:ssh-keys (list ssh-key))))
|
| 564 | (member action (hetzner-api-actions api (list (hetzner-action-id action)))))))
|
| 565 |
|
| 566 | (test-skip %when-no-token)
|
| 567 | (test-assert "hetzner-api-locations-integration"
|
| 568 | (let ((locations (hetzner-api-locations (hetzner-api))))
|
| 569 | (and (> (length locations) 0)
|
| 570 | (every hetzner-location? locations))))
|
| 571 |
|
| 572 | (test-skip %when-no-token)
|
| 573 | (test-assert "hetzner-api-server-types-integration"
|
| 574 | (let ((server-types (hetzner-api-server-types (hetzner-api))))
|
| 575 | (and (> (length server-types) 0)
|
| 576 | (every hetzner-server-type? server-types))))
|
| 577 |
|
| 578 | (test-skip %when-no-token)
|
| 579 | (test-assert "hetzner-api-server-create-integration"
|
| 580 | (with-cleanup-api (api (hetzner-api))
|
| 581 | (let* ((ssh-key (create-ssh-key api %ssh-key))
|
| 582 | (server (create-server api ssh-key)))
|
| 583 | (and (hetzner-server? server)
|
| 584 | (equal? %server-name (hetzner-server-name server))))))
|
| 585 |
|
| 586 | (test-skip %when-no-token)
|
| 587 | (test-assert "hetzner-api-server-delete-integration"
|
| 588 | (with-cleanup-api (api (hetzner-api))
|
| 589 | (let* ((ssh-key (create-ssh-key api %ssh-key))
|
| 590 | (server (create-server api ssh-key))
|
| 591 | (action (hetzner-api-server-delete api server)))
|
| 592 | (and (hetzner-action? action)
|
| 593 | (equal? "delete_server"
|
| 594 | (hetzner-action-command action))))))
|
| 595 |
|
| 596 | (test-skip %when-no-token)
|
| 597 | (test-assert "hetzner-api-server-enable-rescue-system-integration"
|
| 598 | (with-cleanup-api (api (hetzner-api))
|
| 599 | (let* ((ssh-key (create-ssh-key api %ssh-key))
|
| 600 | (server (create-server api ssh-key))
|
| 601 | (action (hetzner-api-server-enable-rescue-system
|
| 602 | api server #:ssh-keys (list ssh-key))))
|
| 603 | (and (hetzner-action? action)
|
| 604 | (equal? "enable_rescue"
|
| 605 | (hetzner-action-command action))))))
|
| 606 |
|
| 607 | (test-skip %when-no-token)
|
| 608 | (test-assert "hetzner-api-server-power-on-integration"
|
| 609 | (with-cleanup-api (api (hetzner-api))
|
| 610 | (let* ((ssh-key (create-ssh-key api %ssh-key))
|
| 611 | (server (create-server api ssh-key))
|
| 612 | (action (hetzner-api-server-power-on api server)))
|
| 613 | (and (hetzner-action? action)
|
| 614 | (equal? "start_server"
|
| 615 | (hetzner-action-command action))))))
|
| 616 |
|
| 617 | (test-skip %when-no-token)
|
| 618 | (test-assert "hetzner-api-server-power-off-integration"
|
| 619 | (with-cleanup-api (api (hetzner-api))
|
| 620 | (let* ((ssh-key (create-ssh-key api %ssh-key))
|
| 621 | (server (create-server api ssh-key))
|
| 622 | (action (hetzner-api-server-power-off api server)))
|
| 623 | (and (hetzner-action? action)
|
| 624 | (equal? "stop_server"
|
| 625 | (hetzner-action-command action))))))
|
| 626 |
|
| 627 | (test-skip %when-no-token)
|
| 628 | (test-assert "hetzner-api-server-reboot-integration"
|
| 629 | (with-cleanup-api (api (hetzner-api))
|
| 630 | (let* ((ssh-key (create-ssh-key api %ssh-key))
|
| 631 | (server (create-server api ssh-key))
|
| 632 | (action (hetzner-api-server-reboot api server)))
|
| 633 | (and (hetzner-action? action)
|
| 634 | (equal? "reboot_server"
|
| 635 | (hetzner-action-command action))))))
|
| 636 |
|
| 637 | (test-skip %when-no-token)
|
| 638 | (test-assert "hetzner-api-servers-integration"
|
| 639 | (with-cleanup-api (api (hetzner-api))
|
| 640 | (let* ((ssh-key (create-ssh-key api %ssh-key))
|
| 641 | (server (create-server api ssh-key)))
|
| 642 | (member server (hetzner-api-servers api)))))
|
| 643 |
|
| 644 | (test-skip %when-no-token)
|
| 645 | (test-assert "hetzner-api-ssh-key-create-integration"
|
| 646 | (with-cleanup-api (api (hetzner-api))
|
| 647 | (let ((ssh-key (create-ssh-key api %ssh-key)))
|
| 648 | (and (hetzner-ssh-key? ssh-key)
|
| 649 | (equal? (hetzner-ssh-key-fingerprint %ssh-key)
|
| 650 | (hetzner-ssh-key-fingerprint ssh-key))
|
| 651 | (equal? (hetzner-ssh-key-name %ssh-key)
|
| 652 | (hetzner-ssh-key-name ssh-key))
|
| 653 | (equal? (hetzner-ssh-key-public-key %ssh-key)
|
| 654 | (hetzner-ssh-key-public-key ssh-key))))))
|
| 655 |
|
| 656 | (test-skip %when-no-token)
|
| 657 | (test-assert "hetzner-api-ssh-key-delete-integration"
|
| 658 | (with-cleanup-api (api (hetzner-api))
|
| 659 | (let ((ssh-key (create-ssh-key api %ssh-key)))
|
| 660 | (and (equal? #t (hetzner-api-ssh-key-delete api ssh-key))
|
| 661 | (not (member ssh-key (hetzner-api-ssh-keys api)))))))
|
| 662 |
|
| 663 | (test-skip %when-no-token)
|
| 664 | (test-assert "hetzner-api-ssh-keys-integration"
|
| 665 | (with-cleanup-api (api (hetzner-api))
|
| 666 | (let ((ssh-key (create-ssh-key api %ssh-key)))
|
| 667 | (member ssh-key (hetzner-api-ssh-keys api)))))
|
| 668 |
|
| 669 | (test-end "machine-hetzner-api")
|
| 670 |
|
| 671 | |
| 672 | |
| 673 | |