docker.scm 3.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. ;; (Programming against the v1.38 interface of docker engine.)
  2. (use-modules (web client)
  3. (web uri)
  4. (json)
  5. (ice-9 iconv))
  6. (define* (connect-to-docker-socket #:key (socket-path "/var/run/docker.sock"))
  7. (let ([docker-sock-addr (make-socket-address AF_UNIX socket-path)]
  8. [docker-sock (socket PF_UNIX SOCK_STREAM 0)])
  9. ;; socket options:
  10. ;; https://www.gnu.org/software/libc/manual/html_node/Socket_002dLevel-Options.html
  11. (setsockopt docker-sock SOL_SOCKET SO_REUSEADDR 1)
  12. ;; usage of connect:
  13. ;; https://www.gnu.org/software/guile/manual/html_node/Network-Sockets-and-Communication.html#Network-Sockets-and-Communication
  14. ;; server side would use `bind`, `accept` and `listen`.
  15. ;; client side uses `connect` and `close`.
  16. (connect docker-sock docker-sock-addr)
  17. docker-sock))
  18. (define (conditionally-make-alist-of names vals)
  19. (cond [(null? names) '()]
  20. [(car vals)
  21. (cons (cons (car names) (car vals))
  22. (conditionally-make-alist-of (cdr names) (cdr vals)))]
  23. [else (conditionally-make-alist-of (cdr names) (cdr vals))]))
  24. (define (alist-to-query-params alist)
  25. (string-join (map (lambda (assoc)
  26. (string-append (car assoc) "=" (cdr assoc)))
  27. alist)
  28. "&"))
  29. (define (make-complete-api-url api-route query-params-as-string)
  30. (string-append api-route "?" query-params-as-string))
  31. (define (scm-json->uri-encoded-string scm-json)
  32. "The argument scm-json is the Scheme representation of guile-json
  33. for JSON."
  34. (uri-encode (scm->json-string scm-json)))
  35. (define* (/containers/json dock-sock #:key (limit #f) (filters #f) (all #f) (size #f))
  36. (define (build-api-url)
  37. (display
  38. (simple-format #f
  39. "URL-ENCODED FILTERS: ~s\n"
  40. (scm-json->uri-encoded-string filters)))
  41. (let* ([filters-url-encoded
  42. (scm-json->uri-encoded-string filters)]
  43. [query-params
  44. (alist-to-query-params
  45. (conditionally-make-alist-of
  46. '("limit" "filters" "all" "size")
  47. (list limit filters-url-encoded all size)))])
  48. (string-append "/containers/json" "?" query-params)))
  49. (call-with-values
  50. (lambda ()
  51. (http-get (build-api-url)
  52. #:port dock-sock
  53. ;; dockerd uses HTTP 1.1 it seems.
  54. ;; other values will result in: "Bad Request: unsupported protocol version"
  55. #:version '(1 . 1)
  56. #:keep-alive? #f
  57. ;; Apparently the `host` header must be specified.
  58. ;; The `host` header in this case is ("localhost" . #f).
  59. ;; The `host` header contains domain and port
  60. #:headers '((host . ("localhost" . #f))
  61. #;(content-type . "application/x-www-form-urlencoded"))
  62. #:decode-body? #t
  63. #:streaming? #f))
  64. (lambda (response response-text)
  65. (display
  66. (simple-format #f
  67. "RESPONSE TEXT: ~s"
  68. (bytevector->string response-text "utf-8")))
  69. (let ([resp-text-as-string (bytevector->string response-text "utf-8")])
  70. (cons response resp-text-as-string)))))
  71. (let ([dock-sock (connect-to-docker-socket)])
  72. (let ([resp-and-resp-text
  73. (/containers/json dock-sock
  74. #:all "true"
  75. #:filters '(("name" . #("db"))
  76. ("status" . #("running" "exited"))))])
  77. (display resp-and-resp-text)
  78. (newline)))