File size: 3,647 Bytes
3b70664
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
(in-package #:nekod.docker)

(defun list-networks (sock)
  "List all Docker networks on this host.

   Returns JSON body as a string."
  (multiple-value-bind (status body)
      (docker-get sock "/networks")
    (if (= status 200) body
        (error 'nekod:docker-api-error :message body :status-code status
               :endpoint "/networks"))))

(defun inspect-network (sock id)
  "Inspect a Docker network by ID or name.

   Returns full JSON metadata as a string."
  (multiple-value-bind (status body)
      (docker-get sock (format nil "/networks/~a" id))
    (if (= status 200) body
        (error 'nekod:docker-api-error :message body :status-code status
               :endpoint (format nil "/networks/~a" id)))))

(defun create-network (sock name &key (driver "bridge") (internal nil) labels)
  "Create a Docker network.

   name     — network name

   driver   — network driver: \"bridge\", \"host\", \"overlay\", \"none\"

   internal — restrict external access when t

   labels   — alist of string key-value pairs

   Returns JSON body (contains network ID) as a string."
  (let ((body (format nil
                      "{\"Name\":~s,\"Driver\":~s,\"Internal\":~a,\"Labels\":{~{~s:~s~^,~}}}"
                      name
                      driver
                      (if internal "true" "false")
                      (loop for (k . v) in (or labels '())
                            nconc (list k v)))))
    (multiple-value-bind (status resp)
        (docker-post sock "/networks/create" body)
      (if (= status 201) resp
          (error 'nekod:docker-api-error :message resp :status-code status
                 :endpoint "/networks/create")))))

(defun remove-network (sock id)
  "Remove a Docker network by ID or name.

   The network must have no active endpoints.

   Returns t on success."
  (multiple-value-bind (status body)
      (docker-delete sock (format nil "/networks/~a" id))
    (if (= status 204) t
        (error 'nekod:docker-api-error :message body :status-code status
               :endpoint (format nil "/networks/~a" id)))))

(defun connect-container-to-network (sock network-id container-id)
  "Connect a running container to a network.

   Returns t on success."
  (let ((body (format nil "{\"Container\":~s}" container-id)))
    (multiple-value-bind (status resp)
        (docker-post sock (format nil "/networks/~a/connect" network-id) body)
      (if (= status 200) t
          (error 'nekod:docker-api-error :message resp :status-code status
                 :endpoint (format nil "/networks/~a/connect" network-id))))))

(defun disconnect-container-from-network (sock network-id container-id &optional (force nil))
  "Disconnect a container from a network.

   force — force disconnect even if the container is still running.

   Returns t on success."
  (let ((body (format nil "{\"Container\":~s,\"Force\":~a}"
                      container-id (if force "true" "false"))))
    (multiple-value-bind (status resp)
        (docker-post sock (format nil "/networks/~a/disconnect" network-id) body)
      (if (= status 200) t
          (error 'nekod:docker-api-error :message resp :status-code status
                 :endpoint (format nil "/networks/~a/disconnect" network-id))))))

(defun prune-networks (sock)
  "Remove all unused Docker networks.

   Returns JSON summary as a string."
  (multiple-value-bind (status body)
      (docker-post sock "/networks/prune")
    (if (= status 200) body
        (error 'nekod:docker-api-error :message body :status-code status
               :endpoint "/networks/prune"))))