home-lab/packages/lab-tool/lab/deployment.scm
2025-06-16 21:09:41 +02:00

139 lines
5.8 KiB
Scheme

;; lab/deployment.scm - Deployment operations (impure)
(define-module (lab deployment)
#:use-module (ice-9 format)
#:use-module (ice-9 popen)
#:use-module (ice-9 textual-ports)
#:use-module (srfi srfi-1)
#:use-module (utils logging)
#:use-module (utils config)
#:use-module (utils ssh)
#:export (deploy-machine
update-flake
execute-nixos-rebuild
option-ref))
;; Helper function for option handling
(define (option-ref options key default)
"Get option value with default fallback"
(let ((value (assoc-ref options key)))
(if value value default)))
;; Impure function: Deploy machine configuration
(define (deploy-machine machine-name . args)
"Deploy configuration to machine (impure - has side effects)"
(let* ((mode (if (null? args) "boot" (car args)))
(options (if (< (length args) 2) '() (cadr args)))
(valid-modes '("boot" "test" "switch"))
(dry-run (option-ref options 'dry-run #f)))
(if (not (validate-machine-name machine-name))
#f
(if (not (member mode valid-modes))
(begin
(log-error "Invalid deployment mode: ~a" mode)
(log-error "Valid modes: ~a" (string-join valid-modes ", "))
#f)
(begin
(log-info "Starting deployment: ~a (mode: ~a)" machine-name mode)
(execute-nixos-rebuild machine-name mode options))))))
;; Impure function: Update flake inputs
(define (update-flake . args)
"Update flake inputs (impure - has side effects)"
(let* ((options (if (null? args) '() (car args)))
(dry-run (option-ref options 'dry-run #f)))
(log-info "Updating flake inputs...")
(if dry-run
(begin
(log-info "DRY RUN: Would execute: nix flake update")
#t)
(let* ((homelab-root (get-homelab-root))
(update-cmd (format #f "cd ~a && nix flake update" homelab-root))
(port (open-pipe* OPEN_READ "/bin/sh" "-c" update-cmd))
(output (get-string-all port))
(status (close-pipe port)))
(if (zero? status)
(begin
(log-success "Flake inputs updated successfully")
#t)
(begin
(log-error "Flake update failed (exit: ~a)" status)
(log-error "Error output: ~a" output)
#f))))))
;; Impure function: Execute nixos-rebuild
(define (execute-nixos-rebuild machine-name mode options)
"Execute nixos-rebuild command (impure - has side effects)"
(let* ((dry-run (option-ref options 'dry-run #f))
(ssh-config (get-ssh-config machine-name))
(is-local (and ssh-config (assoc-ref ssh-config 'is-local)))
(homelab-root (get-homelab-root)))
(if is-local
;; Local deployment
(let ((rebuild-cmd (format #f "sudo nixos-rebuild ~a --flake ~a#~a"
mode homelab-root machine-name)))
(log-debug "Local rebuild command: ~a" rebuild-cmd)
(if dry-run
(begin
(log-info "DRY RUN: Would execute: ~a" rebuild-cmd)
#t)
(let* ((port (open-pipe* OPEN_READ "/bin/sh" "-c" rebuild-cmd))
(output (get-string-all port))
(status (close-pipe port)))
(if (zero? status)
(begin
(log-success "Local nixos-rebuild completed")
#t)
(begin
(log-error "Local nixos-rebuild failed (exit: ~a)" status)
#f)))))
;; Remote deployment
(let* ((hostname (assoc-ref ssh-config 'hostname))
(ssh-alias (or (assoc-ref ssh-config 'ssh-alias) hostname))
(temp-dir "/tmp/homelab-deploy")
(sync-cmd (format #f "rsync -av --delete ~a/ ~a:~a/"
homelab-root ssh-alias temp-dir))
(rebuild-cmd (format #f "ssh ~a 'cd ~a && sudo nixos-rebuild ~a --flake .#~a'"
ssh-alias temp-dir mode machine-name)))
(log-debug "Remote sync command: ~a" sync-cmd)
(log-debug "Remote rebuild command: ~a" rebuild-cmd)
(if dry-run
(begin
(log-info "DRY RUN: Would sync and rebuild remotely")
#t)
(begin
;; Sync configuration
(log-info "Syncing configuration to ~a..." machine-name)
(let* ((sync-port (open-pipe* OPEN_READ "/bin/sh" "-c" sync-cmd))
(sync-output (get-string-all sync-port))
(sync-status (close-pipe sync-port)))
(if (zero? sync-status)
(begin
(log-success "Configuration synced")
;; Execute rebuild
(log-info "Executing nixos-rebuild on ~a..." machine-name)
(let* ((rebuild-port (open-pipe* OPEN_READ "/bin/sh" "-c" rebuild-cmd))
(rebuild-output (get-string-all rebuild-port))
(rebuild-status (close-pipe rebuild-port)))
(if (zero? rebuild-status)
(begin
(log-success "Remote nixos-rebuild completed")
#t)
(begin
(log-error "Remote nixos-rebuild failed (exit: ~a)" rebuild-status)
#f))))
(begin
(log-error "Configuration sync failed (exit: ~a)" sync-status)
#f)))))))))