conlink 2.0.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,286 @@
1
+ digraph {
2
+ splines = true;
3
+ compound = true;
4
+ subgraph "cluster_host" {
5
+ shape = "box";
6
+ fontsize = 14;
7
+ style = "filled";
8
+ penwidth = 1;
9
+ fillcolor = "#f5f5f5";
10
+ color = "#666666";
11
+ label = "host system";
12
+ subgraph "cluster_conlink" {
13
+ shape = "box";
14
+ fontsize = 14;
15
+ style = "rounded,filled";
16
+ penwidth = 3;
17
+ fillcolor = "#c5d1e7";
18
+ color = "#7396a0";
19
+ label = "conlink/network";
20
+ subgraph "cluster_bridge_s1" {
21
+ shape = "box";
22
+ fontsize = 14;
23
+ style = "filled";
24
+ penwidth = 1;
25
+ fillcolor = "#c8badc";
26
+ color = "#6e509f";
27
+ label = "s1";
28
+ }
29
+ subgraph "cluster_bridge_s2" {
30
+ shape = "box";
31
+ fontsize = 14;
32
+ style = "filled";
33
+ penwidth = 1;
34
+ fillcolor = "#c8badc";
35
+ color = "#6e509f";
36
+ label = "s2";
37
+ }
38
+ subgraph "cluster_bridge_s3" {
39
+ shape = "box";
40
+ fontsize = 14;
41
+ style = "filled";
42
+ penwidth = 1;
43
+ fillcolor = "#c8badc";
44
+ color = "#6e509f";
45
+ label = "s3";
46
+ }
47
+ subgraph "cluster_bridge_s1" {
48
+ shape = "box";
49
+ fontsize = 14;
50
+ style = "filled";
51
+ penwidth = 1;
52
+ fillcolor = "#c8badc";
53
+ color = "#6e509f";
54
+ label = "s1";
55
+ "out_DASH_r0_1_DASH_eth_DASH_s1" [
56
+ color = "#af6b4e";
57
+ fillcolor = "#e8e8c8";
58
+ width = 0.1;
59
+ penwidth = 1;
60
+ style = "filled";
61
+ label = "r0_1-eth-s1";
62
+ shape = "box";
63
+ fontsize = 10;
64
+ height = 0.1;
65
+ ];
66
+ "out_DASH_h1_1_DASH_eth0" [
67
+ color = "#af6b4e";
68
+ fillcolor = "#e8e8c8";
69
+ width = 0.1;
70
+ penwidth = 1;
71
+ style = "filled";
72
+ label = "h1_1-eth0";
73
+ shape = "box";
74
+ fontsize = 10;
75
+ height = 0.1;
76
+ ];
77
+ }
78
+ subgraph "cluster_bridge_s2" {
79
+ shape = "box";
80
+ fontsize = 14;
81
+ style = "filled";
82
+ penwidth = 1;
83
+ fillcolor = "#c8badc";
84
+ color = "#6e509f";
85
+ label = "s2";
86
+ "out_DASH_r0_1_DASH_eth_DASH_s2" [
87
+ color = "#af6b4e";
88
+ fillcolor = "#e8e8c8";
89
+ width = 0.1;
90
+ penwidth = 1;
91
+ style = "filled";
92
+ label = "r0_1-eth-s2";
93
+ shape = "box";
94
+ fontsize = 10;
95
+ height = 0.1;
96
+ ];
97
+ "out_DASH_h2_1_DASH_eth0" [
98
+ color = "#af6b4e";
99
+ fillcolor = "#e8e8c8";
100
+ width = 0.1;
101
+ penwidth = 1;
102
+ style = "filled";
103
+ label = "h2_1-eth0";
104
+ shape = "box";
105
+ fontsize = 10;
106
+ height = 0.1;
107
+ ];
108
+ }
109
+ subgraph "cluster_bridge_s3" {
110
+ shape = "box";
111
+ fontsize = 14;
112
+ style = "filled";
113
+ penwidth = 1;
114
+ fillcolor = "#c8badc";
115
+ color = "#6e509f";
116
+ label = "s3";
117
+ "out_DASH_r0_1_DASH_eth_DASH_s3" [
118
+ color = "#af6b4e";
119
+ fillcolor = "#e8e8c8";
120
+ width = 0.1;
121
+ penwidth = 1;
122
+ style = "filled";
123
+ label = "r0_1-eth-s3";
124
+ shape = "box";
125
+ fontsize = 10;
126
+ height = 0.1;
127
+ ];
128
+ "out_DASH_h3_1_DASH_eth0" [
129
+ color = "#af6b4e";
130
+ fillcolor = "#e8e8c8";
131
+ width = 0.1;
132
+ penwidth = 1;
133
+ style = "filled";
134
+ label = "h3_1-eth0";
135
+ shape = "box";
136
+ fontsize = 10;
137
+ height = 0.1;
138
+ ];
139
+ }
140
+ }
141
+ subgraph "cluster_service_r0" {
142
+ shape = "box";
143
+ fontsize = 14;
144
+ style = "rounded,filled";
145
+ penwidth = 2;
146
+ fillcolor = "#c1d0d7";
147
+ color = "#7396a6";
148
+ label = "service 'r0'";
149
+ "r0_COLON_eth_DASH_s1" [
150
+ color = "#af6b4e";
151
+ fillcolor = "#e8e8c8";
152
+ width = 0.1;
153
+ penwidth = 1;
154
+ style = "filled";
155
+ label = "eth-s1";
156
+ shape = "box";
157
+ fontsize = 10;
158
+ height = 0.1;
159
+ ];
160
+ "r0_COLON_eth_DASH_s2" [
161
+ color = "#af6b4e";
162
+ fillcolor = "#e8e8c8";
163
+ width = 0.1;
164
+ penwidth = 1;
165
+ style = "filled";
166
+ label = "eth-s2";
167
+ shape = "box";
168
+ fontsize = 10;
169
+ height = 0.1;
170
+ ];
171
+ "r0_COLON_eth_DASH_s3" [
172
+ color = "#af6b4e";
173
+ fillcolor = "#e8e8c8";
174
+ width = 0.1;
175
+ penwidth = 1;
176
+ style = "filled";
177
+ label = "eth-s3";
178
+ shape = "box";
179
+ fontsize = 10;
180
+ height = 0.1;
181
+ ];
182
+ }
183
+ subgraph "cluster_service_h1" {
184
+ shape = "box";
185
+ fontsize = 14;
186
+ style = "rounded,filled";
187
+ penwidth = 2;
188
+ fillcolor = "#c1d0d7";
189
+ color = "#7396a6";
190
+ label = "service 'h1'";
191
+ "h1_COLON_eth0" [
192
+ color = "#af6b4e";
193
+ fillcolor = "#e8e8c8";
194
+ width = 0.1;
195
+ penwidth = 1;
196
+ style = "filled";
197
+ label = "eth0";
198
+ shape = "box";
199
+ fontsize = 10;
200
+ height = 0.1;
201
+ ];
202
+ }
203
+ subgraph "cluster_service_h2" {
204
+ shape = "box";
205
+ fontsize = 14;
206
+ style = "rounded,filled";
207
+ penwidth = 2;
208
+ fillcolor = "#c1d0d7";
209
+ color = "#7396a6";
210
+ label = "service 'h2'";
211
+ "h2_COLON_eth0" [
212
+ color = "#af6b4e";
213
+ fillcolor = "#e8e8c8";
214
+ width = 0.1;
215
+ penwidth = 1;
216
+ style = "filled";
217
+ label = "eth0";
218
+ shape = "box";
219
+ fontsize = 10;
220
+ height = 0.1;
221
+ ];
222
+ }
223
+ subgraph "cluster_service_h3" {
224
+ shape = "box";
225
+ fontsize = 14;
226
+ style = "rounded,filled";
227
+ penwidth = 2;
228
+ fillcolor = "#c1d0d7";
229
+ color = "#7396a6";
230
+ label = "service 'h3'";
231
+ "h3_COLON_eth0" [
232
+ color = "#af6b4e";
233
+ fillcolor = "#e8e8c8";
234
+ width = 0.1;
235
+ penwidth = 1;
236
+ style = "filled";
237
+ label = "eth0";
238
+ shape = "box";
239
+ fontsize = 10;
240
+ height = 0.1;
241
+ ];
242
+ }
243
+ }
244
+ "r0_COLON_eth_DASH_s1" -> "out_DASH_r0_1_DASH_eth_DASH_s1" [
245
+ shape = "box";
246
+ fontsize = 14;
247
+ style = "filled";
248
+ penwidth = 1;
249
+ label = "";
250
+ ];
251
+ "r0_COLON_eth_DASH_s2" -> "out_DASH_r0_1_DASH_eth_DASH_s2" [
252
+ shape = "box";
253
+ fontsize = 14;
254
+ style = "filled";
255
+ penwidth = 1;
256
+ label = "";
257
+ ];
258
+ "r0_COLON_eth_DASH_s3" -> "out_DASH_r0_1_DASH_eth_DASH_s3" [
259
+ shape = "box";
260
+ fontsize = 14;
261
+ style = "filled";
262
+ penwidth = 1;
263
+ label = "";
264
+ ];
265
+ "h1_COLON_eth0" -> "out_DASH_h1_1_DASH_eth0" [
266
+ shape = "box";
267
+ fontsize = 14;
268
+ style = "filled";
269
+ penwidth = 1;
270
+ label = "";
271
+ ];
272
+ "h2_COLON_eth0" -> "out_DASH_h2_1_DASH_eth0" [
273
+ shape = "box";
274
+ fontsize = 14;
275
+ style = "filled";
276
+ penwidth = 1;
277
+ label = "";
278
+ ];
279
+ "h3_COLON_eth0" -> "out_DASH_h3_1_DASH_eth0" [
280
+ shape = "box";
281
+ fontsize = 14;
282
+ style = "filled";
283
+ penwidth = 1;
284
+ label = "";
285
+ ];
286
+ }
@@ -88,10 +88,9 @@ Resources:
88
88
  # echo "podman ps" | sudo -i -u ubuntu bash
89
89
 
90
90
  ## Download conlink image and repo
91
- docker pull lonocloud/conlink:config-and-cljs-refactor
91
+ docker pull lonocloud/conlink
92
92
  git clone https://github.com/LonoCloud/conlink /root/conlink
93
93
  cd /root/conlink
94
- git checkout -b config-and-cljs-refactor origin/config-and-cljs-refactor
95
94
 
96
95
  #cfn-signal -e 0 --stack ${AWS::StackName} --region ${AWS::Region} --resource WaitHandle
97
96
  cat > /tmp/signal << EOF
package/host-build.yaml CHANGED
@@ -1 +1 @@
1
- services: {network: {volumes: ["../build:/app/build"]}}
1
+ services: {network: {volumes: ["../:/app/"]}}
package/modes0/a/deps ADDED
@@ -0,0 +1 @@
1
+ b,c
package/modes0/b/deps ADDED
@@ -0,0 +1 @@
1
+ c,d
package/modes0/c/deps ADDED
@@ -0,0 +1 @@
1
+ e
package/modes0/e/deps ADDED
@@ -0,0 +1 @@
1
+ f
package/modes1/a/deps ADDED
@@ -0,0 +1 @@
1
+ b c|d
package/modes1/b/deps ADDED
@@ -0,0 +1 @@
1
+ e f
package/modes1/c/deps ADDED
@@ -0,0 +1 @@
1
+ g
package/modes1/d/deps ADDED
@@ -0,0 +1 @@
1
+ g h
package/modes2/a/deps ADDED
@@ -0,0 +1 @@
1
+ b c
package/modes2/b/deps ADDED
@@ -0,0 +1 @@
1
+ c|d
package/modes2/c/deps ADDED
@@ -0,0 +1 @@
1
+ e
package/modes2/d/de ADDED
@@ -0,0 +1 @@
1
+ e
package/modes2/d/deps ADDED
@@ -0,0 +1 @@
1
+ e
package/modes3/ab/deps ADDED
@@ -0,0 +1 @@
1
+ base
@@ -0,0 +1 @@
1
+ base mach3|ab
@@ -0,0 +1 @@
1
+ base
package/modes4/a/deps ADDED
@@ -0,0 +1 @@
1
+ b c
package/modes4/b/deps ADDED
@@ -0,0 +1 @@
1
+ d|c
package/net2dot CHANGED
@@ -8,4 +8,4 @@ die() { echo >&2 "${*}"; exit 1; }
8
8
 
9
9
  [ -e "${NBB}" ] || die "Missing ${NBB}. Maybe run 'npm install' in ${TOP_DIR}?"
10
10
 
11
- exec ${NBB} -cp "${TOP_DIR}/src" -m conlink.net2dot/main "${@}"
11
+ exec ${NBB} "${TOP_DIR}/net2dot.cljs" "${@}"
package/net2dot.cljs ADDED
@@ -0,0 +1,113 @@
1
+ #!/usr/bin/env nbb
2
+
3
+ ;; Copyright (c) 2023, Viasat, Inc
4
+ ;; Licensed under MPL 2.0
5
+
6
+ (ns net2dot
7
+ (:require [clojure.string :as S]
8
+ [clojure.pprint :refer [pprint]]
9
+ [cljs-bean.core :refer [->clj ->js]]
10
+ ["fs" :as fs]
11
+ ["ts-graphviz" :refer [Digraph Subgraph toDot Node Edge]]))
12
+
13
+ ;; Reads JSON network config from stdin and outputs to dot (GraphViz)
14
+
15
+ (def DEFAULT-PROPS {:shape "box" :fontsize 14 :style "filled" :penwidth 1})
16
+ (def CONLINK-PROPS {:fillcolor "#c5d1e7" :color "#7396a0" :style "rounded,filled" :penwidth 3})
17
+ (def CON-PROPS {:fillcolor "#dfe8f1" :color "#7396a6" :style "rounded,filled"})
18
+ (def SVC-PROPS {:fillcolor "#c1d0d7" :color "#7396a6" :style "rounded,filled" :penwidth 2})
19
+ (def BRIDGE-PROPS {:fillcolor "#c8badc" :color "#6e509f"})
20
+ (def HOST-PROPS {:fillcolor "#f5f5f5" :color "#666666"})
21
+ (def INTF-PROPS {:fillcolor "#e8e8c8" :color "#af6b4e" :fontsize 10 :width 0.1 :height 0.1})
22
+ (def NIC-PROPS {:fillcolor "#e8e8c8" :color "#af6b4e" :fontsize 14})
23
+ (def TUN-PROPS {:fillcolor "#a5f5a5" :color "#888888"})
24
+
25
+ (defn dot-id [n]
26
+ (-> (name n)
27
+ (S/replace #"[:]" "_COLON_")
28
+ (S/replace #"[-]" "_DASH_")
29
+ (S/replace #"[*]" "_STAR_")
30
+ (S/replace #"[$]" "_DOLLAR_")
31
+ (S/replace #"[{]" "_LCURLY_")
32
+ (S/replace #"[}]" "_LCURLY_")
33
+ (S/replace #"[ ]" "_SPACE_")))
34
+
35
+ (defn node-props [label props]
36
+ (merge DEFAULT-PROPS props {:label label}))
37
+
38
+ (defn digraph [props]
39
+ (Digraph. (->js {:splines true :compound true})))
40
+
41
+ (defn subgraph [parent id label props]
42
+ (let [n (Subgraph. id (->js (node-props label props)))]
43
+ ^obj (.addSubgraph parent n)
44
+ n))
45
+
46
+ (defn node [parent id label props]
47
+ (let [n (Node. id (->js (node-props label props)))]
48
+ ^obj (.addNode parent n)
49
+ n))
50
+
51
+ (defn edge [parent idA idB label props]
52
+ (let [n (Edge. #js [idA idB] (->js (node-props label props)))]
53
+ ^obj (.addEdge parent n)
54
+ n))
55
+
56
+ (defn render [network-config]
57
+ (let [graph (digraph {:splines true :compound true})
58
+ host (subgraph graph "cluster_host" "host system" HOST-PROPS)
59
+ conlink (subgraph host "cluster_conlink" "conlink/network" CONLINK-PROPS)
60
+ bridges (reduce
61
+ #(->> (subgraph conlink (str "cluster_bridge_" %2)
62
+ %2 BRIDGE-PROPS)
63
+ (assoc %1 %2))
64
+ {} (keep :bridge (:links network-config)))
65
+ services (reduce
66
+ #(->> (subgraph host (str "cluster_service_" (dot-id %2))
67
+ (str "service '" (name %2) "'") SVC-PROPS)
68
+ (assoc %1 %2))
69
+ {} (keys (:services network-config)))
70
+ containers (reduce
71
+ #(->> (subgraph host (str "cluster_container_" (dot-id %2))
72
+ (str "container '" (name %2) "'") CON-PROPS)
73
+ (assoc %1 %2))
74
+ {} (keys (:containers network-config)))]
75
+
76
+ (doseq [link (:links network-config)]
77
+ (let [{:keys [service container dev outer-dev bridge base]} link
78
+ cname (or service container)
79
+ cnode (get (if service services containers) (keyword cname))
80
+ dev-id (str cname ":" (name dev))
81
+ in-intf (node cnode (dot-id dev-id) dev INTF-PROPS)]
82
+ (when (#{:conlink :host} (keyword base))
83
+ (let [outer-dev (or outer-dev
84
+ (str (if service (str service "_1") container)
85
+ "-" (name dev)))
86
+ out-id (str "out-" outer-dev)
87
+ out-parent (condp = (keyword base)
88
+ :conlink (get bridges bridge)
89
+ :host host)
90
+ {:keys [type vlanid]} link
91
+ [elabel iprops] (if (= "host" base)
92
+ [(str (name type) (when vlanid
93
+ (str " " vlanid)))
94
+ NIC-PROPS]
95
+ ["" INTF-PROPS])
96
+ out-intf (node out-parent (dot-id out-id) outer-dev iprops)
97
+ edge (edge graph in-intf out-intf elabel {})]
98
+ true))))
99
+
100
+ (doseq [{:keys [type remote bridge vni]} (:tunnels network-config)]
101
+ (let [br (get bridges bridge)
102
+ rt (node graph (dot-id remote)
103
+ (str "remote host " remote) TUN-PROPS)
104
+ intf (node br (dot-id (str type "-" vni))
105
+ (str type "-" vni) INTF-PROPS)]
106
+ (edge graph intf rt "" {})))
107
+
108
+ (toDot graph)))
109
+
110
+ (let [stdin (fs/readFileSync "/dev/stdin" "utf8")
111
+ network-config (->clj (js/JSON.parse stdin))
112
+ dot-graph (render network-config)]
113
+ (println dot-graph))
package/net2dot.mjs ADDED
@@ -0,0 +1,21 @@
1
+ import { attribute as _, Digraph, Subgraph, Node, Edge, toDot } from 'ts-graphviz';
2
+
3
+ const G = new Digraph();
4
+ const A = new Subgraph('A');
5
+ const node1 = new Node('node1', {
6
+ color: 'red'
7
+ });
8
+ const node2 = new Node('node2', {
9
+ color: 'blue'
10
+ });
11
+ const edge = new Edge([node1, node2], {
12
+ label: 'Edge Label',
13
+ color: 'pink'
14
+ });
15
+ G.addSubgraph(A);
16
+ A.addNode(node1);
17
+ A.addNode(node2);
18
+ A.addEdge(edge);
19
+ const dot = toDot(G);
20
+
21
+ console.log(dot)
@@ -0,0 +1,14 @@
1
+ (ns conlink.net2dot
2
+ (:require ["ts-graphviz" :refer [Digraph, Subgraph, Node, Edge, toDot]]))
3
+
4
+ (let [node1 (Node. "node1" #js {:color "red"})
5
+ node2 (Node. "node2" #js {:color "blue"})
6
+ edge (Edge. #js [node1 node2] #js {:color "pink"
7
+ :label "Edge Label"})
8
+ A (doto (Subgraph. "A")
9
+ (.addNode node1)
10
+ (.addNode node2)
11
+ (.addEdge edge))
12
+ G (doto (Digraph.)
13
+ (.addSubgraph A))]
14
+ (println (toDot G)))
@@ -0,0 +1,114 @@
1
+ #!/usr/bin/env nbb
2
+
3
+ (ns net2dot
4
+ (:require [clojure.string :as S]
5
+ [clojure.pprint :refer [pprint]]
6
+ [cljs-bean.core :refer [->clj ->js]]
7
+ ["fs" :as fs]
8
+ ["ts-graphviz" :refer [Digraph Subgraph toDot Node Edge]]))
9
+
10
+ ;; Reads JSON network config from stdin and outputs to dot (GraphViz)
11
+
12
+ (def DEFAULT-PROPS {:shape "box" :fontsize 14 :style "filled" :penwidth 1})
13
+ (def CONLINK-PROPS {:style "rounded,filled" :fillcolor "#c1b5c7" :color "#9673a6"})
14
+ (def BRIDGE-PROPS {:style "filled" :fillcolor "#dae8fc" :color "#6c8ebf"})
15
+ (def HOST-PROPS {:style "filled" :fillcolor "#f5f5f5" :color "#666666"})
16
+ (def TUN-PROPS {:fillcolor "#a5a5a5" :color "#888888"})
17
+ (def INTF-PROPS {:width 0.1 :height 0.1 :fontsize 10 :fillcolor "#ffbb9e" :color "#d7db00"})
18
+ (def NIC-PROPS {:fontsize 14 :fillcolor "#ffbb9e" :color "#d7db00"})
19
+ (def CONTAINER-PROPS {:style "rounded,filled" :fillcolor "#e1d5e7" :color "#9673a6"})
20
+ (def SERVICE-PROPS (merge CONTAINER-PROPS {:fillcolor "#d1c5e7" :penwidth 2}))
21
+
22
+ (defn dot-id [n]
23
+ (-> (name n)
24
+ (S/replace #"[:]" "_COLON_")
25
+ (S/replace #"[-]" "_DASH_")
26
+ (S/replace #"[*]" "_STAR_")
27
+ (S/replace #"[$]" "_DOLLAR_")
28
+ (S/replace #"[{]" "_LCURLY_")
29
+ (S/replace #"[}]" "_LCURLY_")
30
+ (S/replace #"[ ]" "_SPACE_")))
31
+
32
+ (defn node-props [label props]
33
+ (merge DEFAULT-PROPS props {:label label}))
34
+
35
+ (defn digraph [props]
36
+ (Digraph. (->js {:splines true :compound true})))
37
+
38
+ (defn subgraph [parent id label props]
39
+ (let [n (Subgraph. id (->js (node-props label props)))]
40
+ ^obj (.addSubgraph parent n)
41
+ n))
42
+
43
+ (defn node [parent id label props]
44
+ (let [n (Node. id (->js (node-props label props)))]
45
+ ^obj (.addNode parent n)
46
+ n))
47
+
48
+ (defn edge [parent idA idB label props]
49
+ (let [n (Edge. #js [idA idB] (->js (node-props label props)))]
50
+ ^obj (.addEdge parent n)
51
+ n))
52
+
53
+ (defn render [network-config]
54
+ (let [graph (digraph {:splines true :compound true})
55
+ host (subgraph graph "cluster_host" "host system" HOST-PROPS)
56
+ conlink (subgraph host "cluster_conlink" "conlink/network" CONLINK-PROPS)
57
+ bridges (reduce
58
+ #(assoc %1 %2
59
+ (subgraph conlink (str "cluster_bridge_" %2)
60
+ %2 BRIDGE-PROPS))
61
+ {} (keep :bridge (:links network-config)))
62
+ services (reduce
63
+ #(assoc %1 %2
64
+ (subgraph host
65
+ (str "cluster_service_" (dot-id %2))
66
+ (str "service '" %2 "'") SERVICE-PROPS))
67
+ {} (keys (:services network-config)))
68
+ containers (reduce
69
+ #(assoc %1 %2
70
+ (subgraph host
71
+ (str "cluster_container_" (dot-id %2))
72
+ (str "container '" %2 "'") CONTAINER-PROPS))
73
+ {} (keys (:services network-config)))
74
+ ]
75
+
76
+ (doseq [link links]
77
+ (let [{:keys [service container dev outer-dev bridge base]} link
78
+ cname (or service container)
79
+ cn (get (if service services containers) cname)
80
+ dev-id (str cname ":" (name dev))
81
+ in-intf (node cn (dot-id dev-id) dev INTF-PROPS)]
82
+ (when (#{:conlink :host} (keyword base))
83
+ (let [outer-dev (or outer-dev
84
+ (str (if service (str service "_1") container)
85
+ "-" (name dev)))
86
+ out-id (str "out-" outer-dev)
87
+ out-parent (condp = (keyword base)
88
+ :conlink (get bridges bridge)
89
+ :host host)
90
+ {:keys [type vlanid]} link
91
+ [elabel iprops] (if (= "host" base)
92
+ [(str (name type) (when vlanid
93
+ (str " " vlanid)))
94
+ NIC-PROPS]
95
+ ["" INTF-PROPS])
96
+ out-intf (node out-parent (dot-id out-id) outer-dev iprops)
97
+ edge (edge graph in-intf out-intf elabel {})]
98
+ true))))
99
+
100
+ (doseq [{:keys [type remote bridge vni]} (:tunnels network-config)]
101
+ (let [br (get bridges bridge)
102
+ rt (node graph (dot-id remote)
103
+ (str "remote host " remote) TUN-PROPS)
104
+ intf (node br (dot-id (str type "-" vni))
105
+ (str type "-" vni) INTF-PROPS)]
106
+ (edge graph intf rt "" {})))
107
+
108
+ (toDot graph)))
109
+
110
+ (defn main []
111
+ (let [stdin (fs/readFileSync "/dev/stdin" "utf8")
112
+ network-config (->clj (js/JSON.parse stdin))
113
+ dot-graph (render network-config)]
114
+ (println dot-graph)))