network_drawer 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 62b2a058777853b011aa999b5bbfaff1f5aea5e9
4
- data.tar.gz: ca9f5bdc9aaa639146504074fa6b2d769ecf9656
3
+ metadata.gz: 8e3fd2565dcf2fc91d794f85263bfb54214f6730
4
+ data.tar.gz: 1f7503b24294cec4c9bf6d34cae092d4a2efcb2d
5
5
  SHA512:
6
- metadata.gz: e6368873678680cf9cb5c72f6c666e7f453fe992ce3c8659b9b7fab18eedff3157f7e01ac41c8cbe5d41dca0338e241f101217efd42e2a7258c503013a6eb600
7
- data.tar.gz: 8a6ede793ae512557266d3e48591e77fe55609962c686dd71bff6c07e2cee18eff3a664491225ca47ab952d6bb4bbfe9d4b3cd1246dc598c28b02eecf2a4036d
6
+ metadata.gz: 5a79d2f85c393a680bc50ee2552f81cffed56741570cd6adc3a81dc0058a76bb480f7316194f1aeeb2286e6f0c352c5235b9521e750b04549ceacdf2a94b4723
7
+ data.tar.gz: eef66c5545b072c38df3e58d9f61822510febc96063022b9cb87dbb5bac75b88e7f56d766172930ab5c73c8c0819cdc4b6511b7ac4362e9bf45c467f9ecba1af
data/.gitignore CHANGED
@@ -12,4 +12,5 @@
12
12
  *.so
13
13
  *.o
14
14
  *.a
15
+ *.dot
15
16
  mkmf.log
data/README.md CHANGED
@@ -1,18 +1,20 @@
1
1
  # NetworkDrawer
2
2
 
3
- A network diagram drawer with json.
3
+ A network diagram drawer with json or yaml.
4
+
5
+ [![Gem Version](https://badge.fury.io/rb/network_drawer.svg)](http://badge.fury.io/rb/network_drawer)
4
6
 
5
7
  ## Installation
6
8
 
7
- Ensure you can use [Graphviz](http://www.graphviz.org/), before installing network_drawer,
9
+ Ensure you can use [Graphviz](http://www.graphviz.org/), before installing network_drawer.
8
10
 
9
- You can install Graphviz as follow
11
+ You can install Graphviz as follow.
10
12
  ```
11
13
  # Mac OS X with brew
12
14
  brew install graphviz
13
15
 
14
16
  # CentOS
15
- yum -y install graphviz
17
+ yum install graphviz
16
18
 
17
19
  # Ubuntu
18
20
  apt-get install graphviz
@@ -34,15 +36,19 @@ Or install it yourself as:
34
36
 
35
37
  ## Usage
36
38
 
37
- You can draw a network diagram:
39
+ You can draw a network diagram with a JSON or YAML file with SVG format:
38
40
 
39
41
  $ bundle exec network_drawer draw examples/simple.json
40
42
 
41
- You can draw a network diagram with specified style and png format:
43
+ $ bundle exec network_drawer draw examples/simple.yml
44
+
45
+ You can draw a network diagram with specified style:
42
46
 
43
47
  $ bundle exec network_drawer draw examples/simple.json -s examples/simple_style.json
44
48
 
45
- You can draw a network diagram with specified style and png format:
49
+ $ bundle exec network_drawer draw examples/simple.yml -s examples/simple_style.yml
50
+
51
+ You can draw a network diagram with png format:
46
52
 
47
53
  $ bundle exec network_drawer draw examples/simple.json -f png
48
54
 
@@ -1,26 +1,44 @@
1
1
  {
2
- "layers": {
3
- "Web": {
4
- "nodes": [
2
+ "layers": [
3
+ {
4
+ "Web": {
5
+ "nodes": [
6
+ {
7
+ "WebLB": {
8
+ "ports": ["80/tcp", "443/tcp"],
9
+ "type": "LB",
10
+ "url": "https://github.com/otahi/network_drawer/"
11
+ }
12
+ },
13
+ { "Web001": { "ports": ["80/tcp"] } },
14
+ { "Web002": { "ports": ["80/tcp"] } }
15
+ ]
16
+ },
17
+ "layers": [
5
18
  {
6
- "WebLB": {
7
- "ports": ["80/tcp", "443/tcp"],
8
- "type": "LB",
9
- "url": "https://github.com/otahi/network_drawer/"
19
+ "Image": {
20
+ "nodes": {
21
+ "ImageWeb001": {
22
+ "ports": ["80/tcp"]
23
+ },
24
+ "ImageWeb002": {
25
+ "ports": ["80/tcp"]
26
+ }
27
+ }
10
28
  }
11
- },
12
- { "Web001": { "ports": ["80/tcp"] } },
13
- { "Web002": { "ports": ["80/tcp"] } }
29
+ }
14
30
  ]
15
31
  },
16
- "App": {
17
- "nodes": [
18
- { "AppLB": { "ports": ["80/tcp", "25/tcp"], "type": "LB" } },
19
- { "App001": { "ports": ["80/tcp", "25/tcp"] } },
20
- { "App002": { "ports": ["80/tcp", "25/tcp"] } }
21
- ]
32
+ {
33
+ "App": {
34
+ "nodes": [
35
+ { "AppLB": { "ports": ["80/tcp", "25/tcp"], "type": "LB" } },
36
+ { "App001": { "ports": ["80/tcp", "25/tcp"] } },
37
+ { "App002": { "ports": ["80/tcp", "25/tcp"] } }
38
+ ]
39
+ }
22
40
  }
23
- },
41
+ ],
24
42
  "nodes": [
25
43
  { "Browser": {}, "type": "Client" },
26
44
  { "Mail Server": {}, "type": "Client" }
@@ -6,20 +6,20 @@
6
6
  <!-- Title: simple Pages: 1 -->
7
7
  <svg width="336pt" height="460pt"
8
8
  viewBox="0.00 0.00 336.00 460.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
9
- <g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 456)">
9
+ <g id="0" class="graph" transform="scale(1 1) rotate(0) translate(4 456)">
10
10
  <title>simple</title>
11
11
  <polygon fill="white" stroke="white" points="-4,4 -4,-456 332,-456 332,4 -4,4"/>
12
- <g id="clust1" class="cluster"><title>cluster1</title>
12
+ <g id="1" class="cluster"><title>cluster_Web</title>
13
13
  <polygon fill="none" stroke="black" points="105,-212 105,-408 295,-408 295,-212 105,-212"/>
14
14
  <text text-anchor="middle" x="200" y="-390" font-family="Helvetica,sans-Serif" font-size="14.00">Web</text>
15
15
  </g>
16
- <g id="clust2" class="cluster"><title>cluster3</title>
16
+ <g id="2" class="cluster"><title>cluster_App</title>
17
17
  <polygon fill="none" stroke="black" points="63,-8 63,-204 320,-204 320,-8 63,-8"/>
18
18
  <text text-anchor="middle" x="191.5" y="-186" font-family="Helvetica,sans-Serif" font-size="14.00">App</text>
19
19
  </g>
20
- <!-- 3 -->
21
- <g id="node1" class="node"><title>3</title>
22
- <g id="a_node1"><a xlink:href="https://github.com/otahi/network_drawer/" xlink:title="WebLB">
20
+ <!-- 0 -->
21
+ <g id="0" class="node"><title>0</title>
22
+ <g id="a_0"><a xlink:href="https://github.com/otahi/network_drawer/" xlink:title="WebLB">
23
23
  <path fill="azure" stroke="black" stroke-dasharray="1,5" d="M247,-375.5C247,-375.5 153,-375.5 153,-375.5 147,-375.5 141,-369.5 141,-363.5 141,-363.5 141,-328.5 141,-328.5 141,-322.5 147,-316.5 153,-316.5 153,-316.5 247,-316.5 247,-316.5 253,-316.5 259,-322.5 259,-328.5 259,-328.5 259,-363.5 259,-363.5 259,-369.5 253,-375.5 247,-375.5"/>
24
24
  <polygon fill="none" stroke="black" points="151,-346 151,-369 196,-369 196,-346 151,-346"/>
25
25
  <text text-anchor="start" x="154.431" y="-351.9" font-family="Helvetica,sans-Serif" font-size="14.00">80/tcp</text>
@@ -30,9 +30,9 @@
30
30
  </a>
31
31
  </g>
32
32
  </g>
33
- <!-- 4 -->
34
- <g id="node2" class="node"><title>4</title>
35
- <g id="a_node2"><a xlink:title="Web001">
33
+ <!-- 1 -->
34
+ <g id="1" class="node"><title>1</title>
35
+ <g id="a_1"><a xlink:title="Web001">
36
36
  <polygon fill="none" stroke="black" points="191,-279.5 113,-279.5 113,-220.5 191,-220.5 191,-279.5"/>
37
37
  <polygon fill="none" stroke="black" points="123,-250 123,-273 181,-273 181,-250 123,-250"/>
38
38
  <text text-anchor="start" x="132.931" y="-255.9" font-family="Helvetica,sans-Serif" font-size="14.00">80/tcp</text>
@@ -41,14 +41,14 @@
41
41
  </a>
42
42
  </g>
43
43
  </g>
44
- <!-- 3&#45;&gt;4 -->
45
- <g id="edge4" class="edge"><title>3&#45;&gt;4:p80tcp</title>
44
+ <!-- 0&#45;&gt;1 -->
45
+ <g id="3" class="edge"><title>0&#45;&gt;1:p80tcp</title>
46
46
  <path fill="none" stroke="blue" d="M199.141,-316.436C198.045,-299.18 195.572,-278.608 190.026,-268.401"/>
47
47
  <polygon fill="blue" stroke="blue" points="192,-265.499 182,-262 187.636,-270.972 192,-265.499"/>
48
48
  </g>
49
- <!-- 5 -->
50
- <g id="node3" class="node"><title>5</title>
51
- <g id="a_node3"><a xlink:title="Web002">
49
+ <!-- 2 -->
50
+ <g id="2" class="node"><title>2</title>
51
+ <g id="a_2"><a xlink:title="Web002">
52
52
  <polygon fill="none" stroke="black" points="287,-279.5 209,-279.5 209,-220.5 287,-220.5 287,-279.5"/>
53
53
  <polygon fill="none" stroke="black" points="219,-250 219,-273 277,-273 277,-250 219,-250"/>
54
54
  <text text-anchor="start" x="228.931" y="-255.9" font-family="Helvetica,sans-Serif" font-size="14.00">80/tcp</text>
@@ -57,14 +57,14 @@
57
57
  </a>
58
58
  </g>
59
59
  </g>
60
- <!-- 3&#45;&gt;5 -->
61
- <g id="edge5" class="edge"><title>3&#45;&gt;5:p80tcp</title>
60
+ <!-- 0&#45;&gt;2 -->
61
+ <g id="4" class="edge"><title>0&#45;&gt;2:p80tcp</title>
62
62
  <path fill="none" stroke="blue" d="M200.859,-316.436C201.955,-299.18 204.428,-278.608 209.974,-268.401"/>
63
63
  <polygon fill="blue" stroke="blue" points="212.364,-270.972 218,-262 208,-265.499 212.364,-270.972"/>
64
64
  </g>
65
- <!-- 6 -->
66
- <g id="node4" class="node"><title>6</title>
67
- <g id="a_node4"><a xlink:title="AppLB">
65
+ <!-- 3 -->
66
+ <g id="3" class="node"><title>3</title>
67
+ <g id="a_3"><a xlink:title="AppLB">
68
68
  <path fill="azure" stroke="black" stroke-dasharray="1,5" d="M218.25,-171.5C218.25,-171.5 131.75,-171.5 131.75,-171.5 125.75,-171.5 119.75,-165.5 119.75,-159.5 119.75,-159.5 119.75,-124.5 119.75,-124.5 119.75,-118.5 125.75,-112.5 131.75,-112.5 131.75,-112.5 218.25,-112.5 218.25,-112.5 224.25,-112.5 230.25,-118.5 230.25,-124.5 230.25,-124.5 230.25,-159.5 230.25,-159.5 230.25,-165.5 224.25,-171.5 218.25,-171.5"/>
69
69
  <polygon fill="none" stroke="black" points="130,-142 130,-165 175,-165 175,-142 130,-142"/>
70
70
  <text text-anchor="start" x="133.431" y="-147.9" font-family="Helvetica,sans-Serif" font-size="14.00">80/tcp</text>
@@ -75,19 +75,19 @@
75
75
  </a>
76
76
  </g>
77
77
  </g>
78
- <!-- 4&#45;&gt;6 -->
79
- <g id="edge6" class="edge"><title>4&#45;&gt;6:p80tcp</title>
78
+ <!-- 1&#45;&gt;3 -->
79
+ <g id="5" class="edge"><title>1&#45;&gt;3:p80tcp</title>
80
80
  <path fill="none" stroke="blue" d="M152,-220.191C152,-207.217 152,-191.442 152,-176.321"/>
81
81
  <polygon fill="blue" stroke="blue" points="155.5,-176 152,-166 148.5,-176 155.5,-176"/>
82
82
  </g>
83
- <!-- 5&#45;&gt;6 -->
84
- <g id="edge7" class="edge"><title>5&#45;&gt;6:p80tcp</title>
83
+ <!-- 2&#45;&gt;3 -->
84
+ <g id="6" class="edge"><title>2&#45;&gt;3:p80tcp</title>
85
85
  <path fill="none" stroke="blue" d="M212.526,-220.441C192.443,-204.036 169.215,-184.601 158.292,-173.792"/>
86
86
  <polygon fill="blue" stroke="blue" points="161.006,-171.581 152,-166 155.559,-175.979 161.006,-171.581"/>
87
87
  </g>
88
- <!-- 7 -->
89
- <g id="node5" class="node"><title>7</title>
90
- <g id="a_node5"><a xlink:title="App001">
88
+ <!-- 4 -->
89
+ <g id="4" class="node"><title>4</title>
90
+ <g id="a_4"><a xlink:title="App001">
91
91
  <polygon fill="none" stroke="black" points="182.25,-75.5 71.75,-75.5 71.75,-16.5 182.25,-16.5 182.25,-75.5"/>
92
92
  <polygon fill="none" stroke="black" points="82,-46 82,-69 127,-69 127,-46 82,-46"/>
93
93
  <text text-anchor="start" x="85.4312" y="-51.9" font-family="Helvetica,sans-Serif" font-size="14.00">80/tcp</text>
@@ -98,19 +98,19 @@
98
98
  </a>
99
99
  </g>
100
100
  </g>
101
- <!-- 6&#45;&gt;7 -->
102
- <g id="edge8" class="edge"><title>6&#45;&gt;7:p25tcp</title>
101
+ <!-- 3&#45;&gt;4 -->
102
+ <g id="7" class="edge"><title>3&#45;&gt;4:p25tcp</title>
103
103
  <path fill="none" stroke="green" d="M160.623,-112.37C156.71,-102.677 153.148,-91.4558 151.693,-80.2467"/>
104
104
  <polygon fill="green" stroke="green" points="155.167,-79.7409 151,-70 148.183,-80.2135 155.167,-79.7409"/>
105
105
  </g>
106
- <!-- 6&#45;&gt;7 -->
107
- <g id="edge9" class="edge"><title>6&#45;&gt;7:p80tcp</title>
106
+ <!-- 3&#45;&gt;4 -->
107
+ <g id="8" class="edge"><title>3&#45;&gt;4:p80tcp</title>
108
108
  <path fill="none" stroke="blue" d="M126.856,-112.424C116.765,-103.478 108.243,-92.5876 105.197,-79.976"/>
109
109
  <polygon fill="blue" stroke="blue" points="108.667,-79.5118 104,-70 101.716,-80.3458 108.667,-79.5118"/>
110
110
  </g>
111
- <!-- 8 -->
112
- <g id="node6" class="node"><title>8</title>
113
- <g id="a_node6"><a xlink:title="App002">
111
+ <!-- 5 -->
112
+ <g id="5" class="node"><title>5</title>
113
+ <g id="a_5"><a xlink:title="App002">
114
114
  <polygon fill="none" stroke="black" points="311.25,-75.5 200.75,-75.5 200.75,-16.5 311.25,-16.5 311.25,-75.5"/>
115
115
  <polygon fill="none" stroke="black" points="211,-46 211,-69 256,-69 256,-46 211,-46"/>
116
116
  <text text-anchor="start" x="214.431" y="-51.9" font-family="Helvetica,sans-Serif" font-size="14.00">80/tcp</text>
@@ -121,44 +121,44 @@
121
121
  </a>
122
122
  </g>
123
123
  </g>
124
- <!-- 6&#45;&gt;8 -->
125
- <g id="edge10" class="edge"><title>6&#45;&gt;8:p25tcp</title>
124
+ <!-- 3&#45;&gt;5 -->
125
+ <g id="9" class="edge"><title>3&#45;&gt;5:p25tcp</title>
126
126
  <path fill="none" stroke="green" d="M230.267,-125.47C252.302,-116.05 273.686,-101.572 278.832,-80.0328"/>
127
127
  <polygon fill="green" stroke="green" points="282.32,-80.3376 280,-70 275.367,-79.5283 282.32,-80.3376"/>
128
128
  </g>
129
- <!-- 6&#45;&gt;8 -->
130
- <g id="edge11" class="edge"><title>6&#45;&gt;8:p80tcp</title>
129
+ <!-- 3&#45;&gt;5 -->
130
+ <g id="10" class="edge"><title>3&#45;&gt;5:p80tcp</title>
131
131
  <path fill="none" stroke="blue" d="M181.385,-112.436C186.051,-94.4294 192.996,-72.8124 201.291,-63.1294"/>
132
132
  <polygon fill="blue" stroke="blue" points="203.16,-66.0907 210,-58 199.607,-60.059 203.16,-66.0907"/>
133
133
  </g>
134
- <!-- 1 -->
135
- <g id="node7" class="node"><title>1</title>
136
- <g id="a_node7"><a xlink:title="Browser">
134
+ <!-- 6 -->
135
+ <g id="6" class="node"><title>6</title>
136
+ <g id="a_6"><a xlink:title="Browser">
137
137
  <polygon fill="none" stroke="black" points="237,-452 161,-452 161,-416 237,-416 237,-452"/>
138
138
  <text text-anchor="start" x="173.328" y="-427.9" font-family="Helvetica,sans-Serif" font-size="14.00">Browser</text>
139
139
  </a>
140
140
  </g>
141
141
  </g>
142
- <!-- 1&#45;&gt;3 -->
143
- <g id="edge1" class="edge"><title>1&#45;&gt;3:p80tcp</title>
142
+ <!-- 6&#45;&gt;0 -->
143
+ <g id="0" class="edge"><title>6&#45;&gt;0:p80tcp</title>
144
144
  <path fill="none" stroke="blue" d="M187.672,-415.857C182.088,-406.095 176.087,-393.216 173.879,-380.063"/>
145
145
  <polygon fill="blue" stroke="blue" points="177.357,-379.657 173,-370 170.384,-380.267 177.357,-379.657"/>
146
146
  </g>
147
- <!-- 1&#45;&gt;3 -->
148
- <g id="edge2" class="edge"><title>1&#45;&gt;3:p443tcp</title>
147
+ <!-- 6&#45;&gt;0 -->
148
+ <g id="1" class="edge"><title>6&#45;&gt;0:p443tcp</title>
149
149
  <path fill="none" stroke="black" d="M209.893,-415.8C215.261,-406.018 221.032,-393.129 223.155,-380.02"/>
150
150
  <polygon fill="black" stroke="black" points="226.647,-380.259 224,-370 219.672,-379.67 226.647,-380.259"/>
151
151
  </g>
152
- <!-- 2 -->
153
- <g id="node8" class="node"><title>2</title>
154
- <g id="a_node8"><a xlink:title="Mail Server">
152
+ <!-- 7 -->
153
+ <g id="7" class="node"><title>7</title>
154
+ <g id="a_7"><a xlink:title="Mail Server">
155
155
  <polygon fill="none" stroke="black" points="94.25,-268 -0.25,-268 -0.25,-232 94.25,-232 94.25,-268"/>
156
156
  <text text-anchor="start" x="12.1035" y="-243.9" font-family="Helvetica,sans-Serif" font-size="14.00">Mail Server</text>
157
157
  </a>
158
158
  </g>
159
159
  </g>
160
- <!-- 2&#45;&gt;6 -->
161
- <g id="edge3" class="edge"><title>2&#45;&gt;6:p25tcp</title>
160
+ <!-- 7&#45;&gt;3 -->
161
+ <g id="2" class="edge"><title>7&#45;&gt;3:p25tcp</title>
162
162
  <path fill="none" stroke="green" d="M70.1237,-231.94C79.4894,-225.355 90.5446,-217.983 101,-212 139.498,-189.969 190.301,-210.355 198.004,-175.979"/>
163
163
  <polygon fill="green" stroke="green" points="201.489,-176.298 199,-166 194.524,-175.603 201.489,-176.298"/>
164
164
  </g>
@@ -0,0 +1,77 @@
1
+ layers:
2
+ - Web:
3
+ nodes:
4
+ - WebLB:
5
+ ports:
6
+ - 80/tcp
7
+ - 443/tcp
8
+ type: LB
9
+ url: https://github.com/otahi/network_drawer/
10
+ - Web001:
11
+ ports:
12
+ - 80/tcp
13
+ - Web002:
14
+ ports:
15
+ - 80/tcp
16
+ layers:
17
+ - Image:
18
+ nodes:
19
+ ImageWeb001:
20
+ ports:
21
+ - 80/tcp
22
+ ImageWeb002:
23
+ ports:
24
+ - 80/tcp
25
+ - App:
26
+ nodes:
27
+ - AppLB:
28
+ ports:
29
+ - 80/tcp
30
+ - 25/tcp
31
+ type: LB
32
+ - App001:
33
+ ports:
34
+ - 80/tcp
35
+ - 25/tcp
36
+ - App002:
37
+ ports:
38
+ - 80/tcp
39
+ - 25/tcp
40
+ nodes:
41
+ - Browser:
42
+ type: Client
43
+ - Mail Server:
44
+ type: Client
45
+ connections:
46
+ - from: Browser
47
+ to: WebLB:80/tcp
48
+ type: HTTP
49
+ - from: Browser
50
+ to: WebLB:443/tcp
51
+ - from: Mail Server
52
+ to: AppLB:25/tcp
53
+ type: SMTP
54
+ - from: WebLB
55
+ to: Web001:80/tcp
56
+ type: HTTP
57
+ - from: WebLB
58
+ to: Web002:80/tcp
59
+ type: HTTP
60
+ - from: Web001
61
+ to: AppLB:80/tcp
62
+ type: HTTP
63
+ - from: Web002
64
+ to: AppLB:80/tcp
65
+ type: HTTP
66
+ - from: AppLB
67
+ to: App001:25/tcp
68
+ type: SMTP
69
+ - from: AppLB
70
+ to: App001:80/tcp
71
+ type: HTTP
72
+ - from: AppLB
73
+ to: App002:25/tcp
74
+ type: SMTP
75
+ - from: AppLB
76
+ to: App002:80/tcp
77
+ type: HTTP
@@ -1,5 +1,6 @@
1
1
  {
2
2
  "types": {
3
+ "WEB": { "style": "rounded,filled,dotted", "fillcolor": "azure" },
3
4
  "LB": { "style": "rounded,filled,dotted", "fillcolor": "azure" },
4
5
  "HTTP": { "color": "blue" },
5
6
  "SMTP": { "color": "green" }
@@ -1,5 +1,8 @@
1
1
  require 'network_drawer/version'
2
2
  require 'network_drawer/cli'
3
+ require 'network_drawer/element/element'
4
+ require 'network_drawer/element/layer'
5
+ require 'network_drawer/element/node'
6
+ require 'network_drawer/element/connection'
3
7
  require 'network_drawer/diagram'
4
8
  require 'network_drawer/source'
5
- require 'network_drawer/style'
@@ -12,7 +12,8 @@ module NetworkDrawer
12
12
  default: :svg)
13
13
  def draw(source_file)
14
14
  src = Source.read(source_file)
15
- op = { style: Style.read(options[:style]) }
15
+ op = {}
16
+ op = { style: Source.read(options[:style]) } if options[:style]
16
17
  op.merge!(format: options[:format])
17
18
  dest_file = source_file.gsub(File.extname(source_file), '')
18
19
  Diagram.draw(src, dest_file, op)
@@ -5,13 +5,10 @@ module NetworkDrawer
5
5
  class Diagram
6
6
  TOP_LAYER = :networkdrawertop
7
7
  DEFAULT_OPTIONS = {}
8
- DEFAULT_STYLE = { fontname: 'Helvetica' }
9
- DEFAULT_NODE_STYLE = { fontname: 'Helvetica', shape: 'box' }
10
- DEFAULT_LINE_STYLE = {}
11
8
 
12
9
  def self.draw(source, dest_file, options = {})
13
- dia = new(source, dest_file, options)
14
- dia.draw
10
+ diagram = new(source, dest_file, options)
11
+ diagram.draw
15
12
  end
16
13
 
17
14
  def initialize(source, dest_file, options = {})
@@ -22,123 +19,101 @@ module NetworkDrawer
22
19
  File.basename(@dest_file, '.*')
23
20
  @nodes = {}
24
21
  @layers = {}
22
+ @connections = []
25
23
  @style = options[:style]
26
24
  @gv = Gviz.new(@title)
27
25
  end
28
26
 
29
27
  def draw
30
- @gv.global(rankdir: 'TB')
31
- @gv.global(DEFAULT_STYLE)
32
- create_nodes
33
- create_connections
28
+ @layers = create_layers
29
+ @connections = create_connections
30
+ draw_elements
34
31
 
35
32
  @gv.save @dest_file, @options[:format]
36
33
  end
37
34
 
38
35
  private
39
36
 
40
- def create_nodes
41
- built_nodes = build_nodes(TOP_LAYER => @source)
42
- built_nodes[TOP_LAYER].each_value do |t|
43
- @gv.global DEFAULT_STYLE
44
- node_style = { label: t[:label], tooltip: t[:name], URL: t[:url] }
45
- node_style =
46
- override_style(:node, node_style, t[:type])
47
- @gv.node(t[:id], node_style)
48
- end
37
+ def draw_elements
38
+ code = @layers.to_code if @layers
39
+ @connections.each do |c|
40
+ code << c.to_code
41
+ end if @connections
42
+ @gv.graph(&eval("proc {#{code}}"))
43
+ end
49
44
 
50
- built_nodes[:layers].each_pair do |n, l|
51
- layer_name = n
52
- id = "#{@layers.size + 1}".to_sym
53
- @layers.merge!(layer_name => id)
54
- l.each_value do |v|
55
- node_style = { label: v[:label], tooltip: v[:name], URL: v[:url] }
56
- node_style =
57
- override_style(:node, node_style, v[:type])
58
- @gv.subgraph "cluster#{id}" do
59
- global label: layer_name
60
- global DEFAULT_STYLE
61
- node(v[:id], node_style)
62
- end
63
- end
64
- end
45
+ def create_layers(name = TOP_LAYER, source = @source)
46
+ return nil unless source && source.is_a?(Hash)
47
+ layer = Element::Layer.new(source, @style[:types])
48
+ layer.name = name
49
+ layer.layers = create_sub_layers(source)
50
+ layer.nodes = create_nodes(source)
51
+ layer
65
52
  end
66
53
 
67
- def build_nodes(layer)
68
- layer_name = layer.keys.first
69
- nodes = layer[layer_name][:nodes]
70
- built_nodes = {}
71
- nodes.each_with_index do |s, i|
72
- id = "#{@nodes.size + 1}".to_sym
73
- name = s.keys.first
74
- ports = s[name][:ports] ? s[name][:ports] : []
75
- url = s[name][:url] ? s[name][:url] : nil
76
- label = build_node_label(name: name, ports: ports)
77
- type = s[name][:type] ? s[name][:type].to_sym : nil
78
- node = {
79
- id: id, name: name, label: label,
80
- ports: ports, type: type, url: url
81
- }
82
- built_nodes.merge!(name => node)
83
- @nodes.merge!(name => node)
84
- end if nodes
85
-
86
- layers = layer[layer_name][:layers]
87
- built_layers = {}
88
- layers.each_pair do |k, v|
89
- built_layers.merge!(build_nodes(k => v))
90
- end if layers
91
- built_nodes = { layer_name => built_nodes, layers: built_layers }
54
+ def create_sub_layers(source)
55
+ return nil unless source && source[:layers]
56
+ sub_layers = []
57
+ source[:layers].each do |l|
58
+ return nil unless l.is_a?(Hash)
59
+ name = l.keys.first
60
+ src = l[name]
61
+ sub_layer = create_layers(name, src) if src
62
+ sub_layers << sub_layer if sub_layer
63
+ end
64
+ sub_layers
92
65
  end
93
66
 
94
- def build_node_label(opt = {})
95
- if opt[:ports].empty?
96
- label = "<tr border='1'><td>#{opt[:name]}</td></tr>"
97
- else
98
- label = "<tr border='1'>"
99
- opt[:ports].each_with_index do |p, j|
100
- label << "<td border='1' port=\"p#{p.gsub('/', '')}\">#{p}</td>"
101
- end
102
- label << '</tr>'
103
- label << "<tr border='1'><td border='1' colspan=\"#{opt[:ports].size}\">#{opt[:name]}</td></tr>"
67
+ def create_nodes(source)
68
+ return nil unless source && source[:nodes]
69
+ nodes = []
70
+ source[:nodes].each do |n|
71
+ return nil unless n.is_a?(Hash)
72
+ node = Element::Node.new(n.values.first, @style[:types])
73
+ node.name = n.keys.first
74
+ @nodes[node.name] = node.id
75
+ nodes << node
104
76
  end
105
- "<table border='0'>#{label}</table>"
77
+ nodes
106
78
  end
107
79
 
108
80
  def create_connections
109
- return if @source[:connections].nil?
110
- seq = 0
81
+ return unless @source[:connections]
82
+ connections = []
111
83
  @source[:connections].each do |c|
112
- from_name, from_port = c[:from].to_s.split(':')
113
- to_name, to_port = c[:to].to_s.split(':')
114
- from_id = @nodes[from_name.to_sym][:id]
115
- to_id = @nodes[to_name.to_sym][:id]
84
+ from_name, from_port = c[:from].split(':')
85
+ to_name, to_port = c[:to].split(':')
86
+
87
+ from_name = from_name.to_sym
88
+ to_name = to_name.to_sym
89
+ return unless node_exist?(from_name) && node_exist?(to_name)
116
90
 
117
- from = from_port ? "#{from_id}:p#{from_port}" : from_id
118
- to = to_port ? "#{to_id}:p#{to_port}" : to_id
119
- line_style = override_style(:line, {}, :"#{c[:type]}")
91
+ connection = Element::Connection.new({}, @style[:types])
92
+ c.each_pair { |k, v| connection[k.to_sym] = v }
120
93
 
121
- @gv.edge "#{from}_#{to}_#{seq}".gsub('/', '').to_sym, line_style
122
- seq += 1
94
+ from = from_port ? "#{@nodes[from_name]}:p#{from_port}" : @nodes[from_name]
95
+ to = to_port ? "#{@nodes[to_name]}:p#{to_port}" : @nodes[to_name]
96
+
97
+ connection.from = from
98
+ connection.to = to
99
+ connections << connection
100
+ end
101
+ connections
102
+ end
103
+
104
+ def node_exist?(name)
105
+ return false unless name
106
+ if @nodes[name]
107
+ true
108
+ else
109
+ puts "No #{name} exists"
110
+ false
123
111
  end
124
112
  end
125
113
 
126
- def override_style(type, origin, style_type)
127
-
128
- default =
129
- case type
130
- when :line
131
- DEFAULT_LINE_STYLE
132
- when :node
133
- DEFAULT_NODE_STYLE
134
- else
135
- DEFAULT_STYLE
136
- end
137
- origin = {} unless origin
138
- return default.merge(origin) unless style_type
139
- style = @style[:types][style_type] if @style[:types]
140
- style ||= {}
141
- default.merge(origin).merge(style)
114
+ def node_id(name)
115
+ return nil unless node_exist?(name)
116
+ @nodes[name.to_sym]
142
117
  end
143
118
  end
144
119
  end
@@ -0,0 +1,22 @@
1
+ require 'network_drawer'
2
+
3
+ module NetworkDrawer
4
+ module Element
5
+ # Replesent of connection
6
+ class Connection < Element
7
+ DEFAULT_STYLE = {}
8
+
9
+ def initialize(initial_values = {}, style = {})
10
+ super
11
+ @default_style = DEFAULT_STYLE
12
+ end
13
+
14
+ def to_code
15
+ style = style(self.type).dup
16
+ style.merge!(self.to_hash)
17
+ cid = "#{self.from}_#{self.to}_#{self.id}".gsub('/', '').to_sym
18
+ "edge(:\"#{cid}\", #{style})\n"
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,43 @@
1
+ require 'network_drawer'
2
+ require 'ostruct'
3
+
4
+ require 'gviz'
5
+
6
+ module NetworkDrawer
7
+ module Element
8
+ # Replesent of element
9
+ class Element < OpenStruct
10
+ DEFAULT_STYLE = {}
11
+
12
+ class << self
13
+ def generate_id
14
+ @ids ? @ids += 1 : @ids = 0
15
+ end
16
+ end
17
+
18
+ def initialize(initial_values = {}, style = {})
19
+ super(initial_values)
20
+ self.id = self.class.generate_id
21
+ @default_style = DEFAULT_STYLE
22
+ @style = style
23
+ end
24
+
25
+ def to_hash
26
+ hash = {}
27
+ self.each_pair do |k, v|
28
+ hash.merge!(k.to_sym => v) unless k.to_sym == name
29
+ end
30
+ hash
31
+ end
32
+
33
+ private
34
+
35
+ def style(type)
36
+ # TODO: select multiple types
37
+ type = type.to_sym if type
38
+ style = @style ? @style[type] : {}
39
+ style ? @default_style.merge(style) : @default_style
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,48 @@
1
+ require 'network_drawer'
2
+
3
+ module NetworkDrawer
4
+ module Element
5
+ # Replesent of layer
6
+ class Layer < Element
7
+ DEFAULT_STYLE = { fontname: 'Helvetica' }
8
+
9
+ def initialize(initial_values = {}, style = {})
10
+ super
11
+ @default_style = DEFAULT_STYLE
12
+ end
13
+
14
+ def to_code
15
+ style = style(self.type).dup
16
+ style.merge!(self.to_hash)
17
+ style.delete(:layers)
18
+ style.delete(:nodes)
19
+ style.delete(:connections)
20
+ label = self.name unless Diagram::TOP_LAYER == self.name
21
+
22
+ node_code = ''
23
+ nodes.each { |n| node_code += n.to_code + "\n" } if nodes
24
+ layer_code = ''
25
+ layers.each { |l| layer_code += l.to_code + "\n" } if layers
26
+
27
+ code = ''
28
+ if Diagram::TOP_LAYER == self.name
29
+ code = <<-EOF
30
+ global(#{style})
31
+ #{node_code}
32
+ #{layer_code}
33
+ EOF
34
+ else
35
+ code = <<-EOF
36
+ subgraph "cluster_#{self.name}" do
37
+ global label: "#{label}"
38
+ global(#{style})
39
+ #{node_code}
40
+ #{layer_code}
41
+ end
42
+ EOF
43
+ end
44
+ code
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,39 @@
1
+ require 'network_drawer'
2
+
3
+ module NetworkDrawer
4
+ module Element
5
+ # Replesent of node
6
+ class Node < Element
7
+ DEFAULT_STYLE = { fontname: 'Helvetica', shape: 'box' }
8
+
9
+ def initialize(initial_values = {}, style = {})
10
+ super
11
+ @default_style = DEFAULT_STYLE
12
+ end
13
+
14
+ def to_code
15
+ style = style(self.type).dup
16
+ style.merge!(self.to_hash)
17
+ style.merge!(label: build_label, tooltip: self.name, URL: self.url )
18
+ style.merge!(ports: nil)
19
+ "node(:\"#{self.id}\", #{style})"
20
+ end
21
+
22
+ private
23
+
24
+ def build_label
25
+ if self.ports && self.ports.size > 0
26
+ label = "<tr border='1'>"
27
+ self.ports.each_with_index do |p, j|
28
+ label << "<td border='1' port=\"p#{p.gsub('/', '')}\">#{p}</td>"
29
+ end
30
+ label << '</tr>'
31
+ label << "<tr border='1'><td border='1' colspan=\"#{self.ports.size}\">#{self.name}</td></tr>"
32
+ else
33
+ label = "<tr border='1'><td>#{self.name}</td></tr>"
34
+ end
35
+ "<table border='0'>#{label}</table>"
36
+ end
37
+ end
38
+ end
39
+ end
@@ -1,10 +1,44 @@
1
1
  require 'json'
2
+ require 'yaml'
2
3
 
3
4
  module NetworkDrawer
4
5
  # Replesent of source file
5
6
  class Source
6
- def self.read(file_name, type = :json)
7
- JSON.parse(File.read(file_name), symbolize_names: true)
7
+ def self.read(file_name)
8
+ source = {}
9
+ case file_type(file_name)
10
+ when :json
11
+ source = JSON.parse(File.read(file_name), symbolize_names: true)
12
+ when :yaml
13
+ source = symbolize(YAML.load(File.read(file_name)))
14
+ else
15
+ puts 'Incorrect file type'
16
+ exit 1
17
+ end
18
+ source
19
+ end
20
+
21
+ def self.file_type(file_name)
22
+ return nil unless file_name
23
+ case file_name
24
+ when /\.json$/
25
+ :json
26
+ when /\.ya?ml$/
27
+ :yaml
28
+ else
29
+ nil
30
+ end
31
+ end
32
+ def self.symbolize(obj)
33
+ return obj.inject({}) do |memo, (k, v)|
34
+ memo[k.to_sym] = symbolize(v)
35
+ memo
36
+ end if obj.is_a? Hash
37
+ return obj.inject([]) do |memo, v|
38
+ memo << symbolize(v)
39
+ memo
40
+ end if obj.is_a? Array
41
+ return obj
8
42
  end
9
43
  end
10
44
  end
@@ -1,3 +1,3 @@
1
1
  module NetworkDrawer
2
- VERSION = '0.1.0'
2
+ VERSION = '0.1.1'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: network_drawer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hiroshi Ota
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-02-21 00:00:00.000000000 Z
11
+ date: 2015-03-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: gviz
@@ -108,16 +108,19 @@ files:
108
108
  - README.md
109
109
  - Rakefile
110
110
  - bin/network_drawer
111
- - examples/simple.dot
112
111
  - examples/simple.json
113
112
  - examples/simple.png
114
113
  - examples/simple.svg
114
+ - examples/simple.yml
115
115
  - examples/simple_style.json
116
116
  - lib/network_drawer.rb
117
117
  - lib/network_drawer/cli.rb
118
118
  - lib/network_drawer/diagram.rb
119
+ - lib/network_drawer/element/connection.rb
120
+ - lib/network_drawer/element/element.rb
121
+ - lib/network_drawer/element/layer.rb
122
+ - lib/network_drawer/element/node.rb
119
123
  - lib/network_drawer/source.rb
120
- - lib/network_drawer/style.rb
121
124
  - lib/network_drawer/version.rb
122
125
  - network_drawer.gemspec
123
126
  homepage: https://github.com/otahi/network_drawer
@@ -1,53 +0,0 @@
1
- digraph simple {
2
- subgraph cluster1 {
3
- label="Web";
4
- fontname="Helvetica";
5
- 3[fontname="Helvetica",shape="box",label=<<table border='0'><tr border='1'><td border='1' port="p80tcp">80/tcp</td><td border='1' port="p443tcp">443/tcp</td></tr><tr border='1'><td border='1' colspan="2">WebLB</td></tr></table>>,tooltip="WebLB",URL="https://github.com/otahi/network_drawer/",style="rounded,filled,dotted",fillcolor="azure"];
6
- }
7
- subgraph cluster1 {
8
- label="Web";
9
- fontname="Helvetica";
10
- 4[fontname="Helvetica",shape="box",label=<<table border='0'><tr border='1'><td border='1' port="p80tcp">80/tcp</td></tr><tr border='1'><td border='1' colspan="1">Web001</td></tr></table>>,tooltip="Web001",URL=""];
11
- }
12
- subgraph cluster1 {
13
- label="Web";
14
- fontname="Helvetica";
15
- 5[fontname="Helvetica",shape="box",label=<<table border='0'><tr border='1'><td border='1' port="p80tcp">80/tcp</td></tr><tr border='1'><td border='1' colspan="1">Web002</td></tr></table>>,tooltip="Web002",URL=""];
16
- }
17
- subgraph cluster3 {
18
- label="App";
19
- fontname="Helvetica";
20
- 6[fontname="Helvetica",shape="box",label=<<table border='0'><tr border='1'><td border='1' port="p80tcp">80/tcp</td><td border='1' port="p25tcp">25/tcp</td></tr><tr border='1'><td border='1' colspan="2">AppLB</td></tr></table>>,tooltip="AppLB",URL="",style="rounded,filled,dotted",fillcolor="azure"];
21
- }
22
- subgraph cluster3 {
23
- label="App";
24
- fontname="Helvetica";
25
- 7[fontname="Helvetica",shape="box",label=<<table border='0'><tr border='1'><td border='1' port="p80tcp">80/tcp</td><td border='1' port="p25tcp">25/tcp</td></tr><tr border='1'><td border='1' colspan="2">App001</td></tr></table>>,tooltip="App001",URL=""];
26
- }
27
- subgraph cluster3 {
28
- label="App";
29
- fontname="Helvetica";
30
- 8[fontname="Helvetica",shape="box",label=<<table border='0'><tr border='1'><td border='1' port="p80tcp">80/tcp</td><td border='1' port="p25tcp">25/tcp</td></tr><tr border='1'><td border='1' colspan="2">App002</td></tr></table>>,tooltip="App002",URL=""];
31
- }
32
- rankdir="TB";
33
- fontname="Helvetica";
34
- 1[fontname="Helvetica",shape="box",label=<<table border='0'><tr border='1'><td>Browser</td></tr></table>>,tooltip="Browser",URL=""];
35
- 2[fontname="Helvetica",shape="box",label=<<table border='0'><tr border='1'><td>Mail Server</td></tr></table>>,tooltip="Mail Server",URL=""];
36
- 3;
37
- 6;
38
- 4;
39
- 5;
40
- 7;
41
- 8;
42
- 1 -> 3:p80tcp[color="blue"];
43
- 1 -> 3:p443tcp;
44
- 2 -> 6:p25tcp[color="green"];
45
- 3 -> 4:p80tcp[color="blue"];
46
- 3 -> 5:p80tcp[color="blue"];
47
- 4 -> 6:p80tcp[color="blue"];
48
- 5 -> 6:p80tcp[color="blue"];
49
- 6 -> 7:p25tcp[color="green"];
50
- 6 -> 7:p80tcp[color="blue"];
51
- 6 -> 8:p25tcp[color="green"];
52
- 6 -> 8:p80tcp[color="blue"];
53
- }
@@ -1,14 +0,0 @@
1
- require 'json'
2
-
3
- module NetworkDrawer
4
- # Replesent of style file
5
- class Style
6
- def self.read(file_name, type = :json)
7
- if file_name
8
- JSON.parse(File.read(file_name), symbolize_names: true)
9
- else
10
- {}
11
- end
12
- end
13
- end
14
- end