#!@GUILE@ --no-auto-compile -*- scheme -*- -*- geiser-scheme-implementation: guile -*- !# ;;; Guix Build Coordinator ;;; ;;; Copyright © 2020 Christopher Baines ;;; ;;; This file is part of the guix-build-coordinator. ;;; ;;; guix-data-service is free software; you can redistribute it and/or modify it ;;; under the terms of the GNU General Public License as published by ;;; the Free Software Foundation; either version 3 of the License, or ;;; (at your option) any later version. ;;; ;;; guix-data-service is distributed in the hope that it will be useful, but ;;; WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;;; General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with the guix-data-service. If not, see ;;; . (use-modules (srfi srfi-1) (srfi srfi-11) (srfi srfi-37) (ice-9 threads) (ice-9 textual-ports) (ice-9 suspendable-ports) ((guix config) #:prefix guix-config:) (guix-build-coordinator utils) (guix-build-coordinator agent) (guix-build-coordinator agent-messaging) (guix-build-coordinator agent-messaging http)) (install-suspendable-ports!) (define %options ;; Specifications of the command-line options (list (option '("coordinator") #t #f (lambda (opt name arg result) (alist-cons 'coordinator arg result))) (option '("uuid") #t #f (lambda (opt name arg result) (alist-cons 'uuid arg result))) (option '("name") #t #f (lambda (opt name arg result) (alist-cons 'name arg result))) (option '("password") #t #f (lambda (opt name arg result) (alist-cons 'password arg result))) (option '("password-file") #t #f (lambda (opt name arg result) (alist-cons 'password (string-trim-right (call-with-input-file arg get-string-all)) result))) (option '("dynamic-auth-token") #t #f (lambda (opt name arg result) (alist-cons 'dynamic-auth-token arg result))) (option '("dynamic-auth-token-file") #t #f (lambda (opt name arg result) (alist-cons 'dynamic-auth-token (string-trim-right (call-with-input-file arg get-string-all)) result))) (option '("max-parallel-uploads") #t #f (lambda (opt name arg result) (alist-cons 'max-parallel-uploads (string->number arg) result))) (option '("max-parallel-builds") #t #f (lambda (opt name arg result) (alist-cons 'max-parallel-builds (string->number arg) result))) (option '("max-allocated-builds") #t #f (lambda (opt name arg result) (alist-cons 'max-allocated-builds (string->number arg) result))) (option '("max-1min-load-average") #t #f (lambda (opt name arg result) (alist-cons 'max-1min-load-average (string->number arg) result))) (option '("substitute-urls") #t #f (lambda (opt name arg result) (alist-cons 'substitute-urls (string-split arg #\space) result))) (option '("derivation-substitute-urls") #t #f (lambda (opt name arg result) (alist-cons 'derivation-substitute-urls (string-split arg #\space) result))) (option '("non-derivation-substitute-urls") #t #f (lambda (opt name arg result) (alist-cons 'non-derivation-substitute-urls (string-split arg #\space) result))) (option '("system") #t #f (lambda (opt name arg result) (alist-cons 'systems (cons arg (or (assq-ref result 'systems) '())) (alist-delete 'systems result)))) (option '("metrics-file") #t #f (lambda (opt name arg result) (alist-cons 'metrics-file arg result))))) (define %option-defaults `((coordinator . "http://localhost:8745") (max-parallel-builds . 1) (max-parallel-uploads . 1) (systems . (,guix-config:%system)) (metrics-file . "/var/lib/prometheus/node-exporter/guix-build-coordinator-agent.prom") (max-1min-load-average . ,(max (ceiling (* 3 (/ (total-processor-count) 4))) 1)))) (define (parse-options options defaults args) (args-fold args %options (lambda (opt name arg result) (error "unrecognized option" name)) (lambda (arg result) (error "unrecognized argument" arg)) %option-defaults)) (setvbuf (current-output-port) 'line) (setvbuf (current-error-port) 'line) (let ((columns (string->number (or (getenv "COLUMNS") "")))) (setenv "COLUMNS" (number->string (if columns (max 256 columns) 256)))) (simple-format (current-error-port) "locale is ~A\n" (check-locale!)) (let ((opts (parse-options %options %option-defaults (cdr (program-arguments))))) (let-values (((uuid coordinator-interface) (cond ((and (string? (assq-ref opts 'uuid)) (string? (assq-ref opts 'password))) (values (assq-ref opts 'uuid) (make-http-agent-interface (assq-ref opts 'coordinator) (assq-ref opts 'uuid) (assq-ref opts 'password)))) ((and (string? (assq-ref opts 'name)) (string? (assq-ref opts 'dynamic-auth-token))) (let ((session-credentials (fetch-session-credentials (assq-ref opts 'coordinator) (assq-ref opts 'name) (assq-ref opts 'dynamic-auth-token)))) (values (assoc-ref session-credentials "id") (make-http-agent-interface (assq-ref opts 'coordinator) (assoc-ref session-credentials "id") (assoc-ref session-credentials "password"))))) (else (error "unknown coordinator interface"))))) (run-agent uuid coordinator-interface (delete-duplicates (assq-ref opts 'systems)) (assq-ref opts 'max-parallel-builds) (assq-ref opts 'max-allocated-builds) (assq-ref opts 'max-parallel-uploads) (or (assq-ref opts 'derivation-substitute-urls) (assq-ref opts 'substitute-urls)) (or (assq-ref opts 'non-derivation-substitute-urls) (assq-ref opts 'substitute-urls)) (assq-ref opts 'metrics-file) (assq-ref opts 'max-1min-load-average))))