docker2plantuml 0.1.0
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.
- checksums.yaml +7 -0
- data/.circleci/config.yml +20 -0
- data/.gitignore +14 -0
- data/.rspec +3 -0
- data/.rubocop.yml +16 -0
- data/.travis.yml +5 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +21 -0
- data/README.md +49 -0
- data/Rakefile +8 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/docker2plantuml.gemspec +40 -0
- data/exe/docker2plantuml +5 -0
- data/lib/docker2plantuml.rb +10 -0
- data/lib/docker2plantuml/command.rb +31 -0
- data/lib/docker2plantuml/model.rb +36 -0
- data/lib/docker2plantuml/parser.rb +68 -0
- data/lib/docker2plantuml/version.rb +12 -0
- data/lib/docker2plantuml/writer.rb +82 -0
- data/readme_sample.svg +31 -0
- metadata +136 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: f2dc86c26f8dae2afb4fa317b03c0a88e2cf7a64b2ef9b4a06711b266333a677
|
|
4
|
+
data.tar.gz: 532b2cf2f6e668212f8229760c259996740e7d0d9f7f1fdef7cfee8accd3b6e0
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 332634b5f7090ea03317db85894353e99fafcb6bc0736fc28bb1a39cd48e1c1c0260c5c76a3334d8acc601773289ab7655b4ae6cd949cfdef177cd0a84f67d64
|
|
7
|
+
data.tar.gz: 129f4f330f3c0ccd983c2ff981abf21e8432828deb16ba50f1e5bce1e6406cfcc7495fc7f0a0ab1301eab0674c76e53d70540f5b6d7711d48cdd9d03d0bb9ad2
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
jobs:
|
|
3
|
+
build:
|
|
4
|
+
docker:
|
|
5
|
+
- image: circleci/ruby
|
|
6
|
+
steps:
|
|
7
|
+
- checkout
|
|
8
|
+
- run: echo "hello world"
|
|
9
|
+
- run: pwd; ls
|
|
10
|
+
- run:
|
|
11
|
+
name: install dependencies
|
|
12
|
+
command: |
|
|
13
|
+
gem install bundler
|
|
14
|
+
bundle install --retry=3 --jobs=4
|
|
15
|
+
- run:
|
|
16
|
+
name: rubocop
|
|
17
|
+
command: bundle exec rake rubocop
|
|
18
|
+
- run:
|
|
19
|
+
name: run tests
|
|
20
|
+
command: bundle exec rake
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.rubocop.yml
ADDED
data/.travis.yml
ADDED
data/CODE_OF_CONDUCT.md
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# Contributor Covenant Code of Conduct
|
|
2
|
+
|
|
3
|
+
## Our Pledge
|
|
4
|
+
|
|
5
|
+
In the interest of fostering an open and welcoming environment, we as
|
|
6
|
+
contributors and maintainers pledge to making participation in our project and
|
|
7
|
+
our community a harassment-free experience for everyone, regardless of age, body
|
|
8
|
+
size, disability, ethnicity, gender identity and expression, level of experience,
|
|
9
|
+
nationality, personal appearance, race, religion, or sexual identity and
|
|
10
|
+
orientation.
|
|
11
|
+
|
|
12
|
+
## Our Standards
|
|
13
|
+
|
|
14
|
+
Examples of behavior that contributes to creating a positive environment
|
|
15
|
+
include:
|
|
16
|
+
|
|
17
|
+
* Using welcoming and inclusive language
|
|
18
|
+
* Being respectful of differing viewpoints and experiences
|
|
19
|
+
* Gracefully accepting constructive criticism
|
|
20
|
+
* Focusing on what is best for the community
|
|
21
|
+
* Showing empathy towards other community members
|
|
22
|
+
|
|
23
|
+
Examples of unacceptable behavior by participants include:
|
|
24
|
+
|
|
25
|
+
* The use of sexualized language or imagery and unwelcome sexual attention or
|
|
26
|
+
advances
|
|
27
|
+
* Trolling, insulting/derogatory comments, and personal or political attacks
|
|
28
|
+
* Public or private harassment
|
|
29
|
+
* Publishing others' private information, such as a physical or electronic
|
|
30
|
+
address, without explicit permission
|
|
31
|
+
* Other conduct which could reasonably be considered inappropriate in a
|
|
32
|
+
professional setting
|
|
33
|
+
|
|
34
|
+
## Our Responsibilities
|
|
35
|
+
|
|
36
|
+
Project maintainers are responsible for clarifying the standards of acceptable
|
|
37
|
+
behavior and are expected to take appropriate and fair corrective action in
|
|
38
|
+
response to any instances of unacceptable behavior.
|
|
39
|
+
|
|
40
|
+
Project maintainers have the right and responsibility to remove, edit, or
|
|
41
|
+
reject comments, commits, code, wiki edits, issues, and other contributions
|
|
42
|
+
that are not aligned to this Code of Conduct, or to ban temporarily or
|
|
43
|
+
permanently any contributor for other behaviors that they deem inappropriate,
|
|
44
|
+
threatening, offensive, or harmful.
|
|
45
|
+
|
|
46
|
+
## Scope
|
|
47
|
+
|
|
48
|
+
This Code of Conduct applies both within project spaces and in public spaces
|
|
49
|
+
when an individual is representing the project or its community. Examples of
|
|
50
|
+
representing a project or community include using an official project e-mail
|
|
51
|
+
address, posting via an official social media account, or acting as an appointed
|
|
52
|
+
representative at an online or offline event. Representation of a project may be
|
|
53
|
+
further defined and clarified by project maintainers.
|
|
54
|
+
|
|
55
|
+
## Enforcement
|
|
56
|
+
|
|
57
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
|
58
|
+
reported by contacting the project team at unapon.dev@gmail.com. All
|
|
59
|
+
complaints will be reviewed and investigated and will result in a response that
|
|
60
|
+
is deemed necessary and appropriate to the circumstances. The project team is
|
|
61
|
+
obligated to maintain confidentiality with regard to the reporter of an incident.
|
|
62
|
+
Further details of specific enforcement policies may be posted separately.
|
|
63
|
+
|
|
64
|
+
Project maintainers who do not follow or enforce the Code of Conduct in good
|
|
65
|
+
faith may face temporary or permanent repercussions as determined by other
|
|
66
|
+
members of the project's leadership.
|
|
67
|
+
|
|
68
|
+
## Attribution
|
|
69
|
+
|
|
70
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
|
71
|
+
available at [http://contributor-covenant.org/version/1/4][version]
|
|
72
|
+
|
|
73
|
+
[homepage]: http://contributor-covenant.org
|
|
74
|
+
[version]: http://contributor-covenant.org/version/1/4/
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2018 unapon
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
[](https://badge.fury.io/gh/unapon%2Fdocker2plantuml)
|
|
2
|
+
[](https://circleci.com/gh/unapon/docker2plantuml)
|
|
3
|
+
[](LICENSE)
|
|
4
|
+
|
|
5
|
+
# Docker2plantuml
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
Add this line to your application's Gemfile:
|
|
10
|
+
|
|
11
|
+
```ruby
|
|
12
|
+
gem 'docker2plantuml'
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
And then execute:
|
|
16
|
+
|
|
17
|
+
$ bundle
|
|
18
|
+
|
|
19
|
+
Or install it yourself as:
|
|
20
|
+
|
|
21
|
+
$ gem install docker2plantuml
|
|
22
|
+
|
|
23
|
+
## Usage
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
$ docker ps -q | xargs docker inspect | docker2plantuml
|
|
27
|
+
```
|
|
28
|
+
or
|
|
29
|
+
```
|
|
30
|
+
$ docker ps -q | xargs docker inspect > docker.json
|
|
31
|
+
$ docker2plantuml docker.json
|
|
32
|
+
```
|
|
33
|
+
And, Convert standard output to deployment diagram using plantUML
|
|
34
|
+
|
|
35
|
+
Example:
|
|
36
|
+
|
|
37
|
+

|
|
38
|
+
|
|
39
|
+
## Contributing
|
|
40
|
+
|
|
41
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/unapon/docker2plantuml. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
|
42
|
+
|
|
43
|
+
## License
|
|
44
|
+
|
|
45
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
|
46
|
+
|
|
47
|
+
## Code of Conduct
|
|
48
|
+
|
|
49
|
+
Everyone interacting in the Docker2plantuml project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/unapon/docker2plantuml/blob/master/CODE_OF_CONDUCT.md).
|
data/Rakefile
ADDED
data/bin/console
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require 'bundler/setup'
|
|
4
|
+
require 'docker2plantuml'
|
|
5
|
+
|
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
|
8
|
+
|
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
|
10
|
+
# require "pry"
|
|
11
|
+
# Pry.start
|
|
12
|
+
|
|
13
|
+
require 'irb'
|
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
|
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
|
+
require "docker2plantuml/version"
|
|
5
|
+
|
|
6
|
+
Gem::Specification.new do |spec|
|
|
7
|
+
spec.name = "docker2plantuml"
|
|
8
|
+
spec.version = Docker2plantuml::VERSION
|
|
9
|
+
spec.authors = ["unapon"]
|
|
10
|
+
spec.email = ["unapon.dev@gmail.com"]
|
|
11
|
+
|
|
12
|
+
spec.summary = %q{Generate PlantUML from "docker inspect" command.}
|
|
13
|
+
spec.description = %q{Generate PlantUML from "docker inspect" command.}
|
|
14
|
+
spec.homepage = "https://github.com/unapon/docker2plantuml"
|
|
15
|
+
spec.license = "MIT"
|
|
16
|
+
|
|
17
|
+
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
|
|
18
|
+
# to allow pushing to a single host or delete this section to allow pushing to any host.
|
|
19
|
+
=begin
|
|
20
|
+
if spec.respond_to?(:metadata)
|
|
21
|
+
spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
|
|
22
|
+
else
|
|
23
|
+
raise "RubyGems 2.0 or newer is required to protect against " \
|
|
24
|
+
"public gem pushes."
|
|
25
|
+
end
|
|
26
|
+
=end
|
|
27
|
+
|
|
28
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
|
29
|
+
f.match(%r{^(test|spec|features)/})
|
|
30
|
+
end
|
|
31
|
+
spec.bindir = "exe"
|
|
32
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
33
|
+
spec.require_paths = ["lib"]
|
|
34
|
+
|
|
35
|
+
spec.add_development_dependency "bundler", "~> 1.16"
|
|
36
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
|
37
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
|
38
|
+
spec.add_development_dependency "rubocop", '~> 0.61.1'
|
|
39
|
+
spec.add_development_dependency "simplecov", "~> 0.16.1"
|
|
40
|
+
end
|
data/exe/docker2plantuml
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Docker2plantuml
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
require_relative 'docker2plantuml/command'
|
|
7
|
+
require_relative 'docker2plantuml/model'
|
|
8
|
+
require_relative 'docker2plantuml/parser'
|
|
9
|
+
require_relative 'docker2plantuml/writer'
|
|
10
|
+
require_relative 'docker2plantuml/version'
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'json'
|
|
4
|
+
|
|
5
|
+
module Docker2plantuml
|
|
6
|
+
class Command
|
|
7
|
+
def self.run(argv)
|
|
8
|
+
new(argv).run
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def initialize(argv)
|
|
12
|
+
@argv = argv
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def run
|
|
16
|
+
json_data = if stdin?
|
|
17
|
+
JSON.parse(STDIN.read)
|
|
18
|
+
else
|
|
19
|
+
JSON.parse(File.read(@argv[0]))
|
|
20
|
+
end
|
|
21
|
+
containers = Docker2plantuml::DockerJsonParser.new(json_data).parse
|
|
22
|
+
w = Docker2plantuml::PlantUMLWriter.new(containers)
|
|
23
|
+
puts Docker2plantuml::HEADER
|
|
24
|
+
puts w.to_plant_uml
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def stdin?
|
|
28
|
+
File.pipe?(STDIN) || !File.select([STDIN], [], [], 0).nil?
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Docker2plantuml
|
|
4
|
+
class DockerContainer
|
|
5
|
+
attr_accessor :container_name, :status, :network_setting, :port_info_list
|
|
6
|
+
|
|
7
|
+
def initialize(name, status)
|
|
8
|
+
@container_name = name
|
|
9
|
+
@status = status
|
|
10
|
+
@port_info_list = []
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def server_port_list
|
|
14
|
+
@port_info_list
|
|
15
|
+
.map(&:host_port)
|
|
16
|
+
.select { |p| p.is_a? String }
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
class NetworkSetting
|
|
21
|
+
attr_accessor :network_name
|
|
22
|
+
|
|
23
|
+
def initialize(name)
|
|
24
|
+
@network_name = name
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
class PortInfo
|
|
29
|
+
attr_accessor :container_port, :host_port
|
|
30
|
+
|
|
31
|
+
def initialize(port, host_port = nil)
|
|
32
|
+
@container_port = port
|
|
33
|
+
@host_port = host_port
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Docker2plantuml
|
|
4
|
+
class DockerJsonParser
|
|
5
|
+
def initialize(json)
|
|
6
|
+
@json_data = json
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def parse
|
|
10
|
+
@json_data.map do |json|
|
|
11
|
+
container = parse_container(json)
|
|
12
|
+
parse_network_and_port(json, container)
|
|
13
|
+
container
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def parse_container(json)
|
|
18
|
+
Docker2plantuml::DockerContainer.new(
|
|
19
|
+
parse_container_name(json),
|
|
20
|
+
parse_container_status(json)
|
|
21
|
+
)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def parse_container_name(json)
|
|
25
|
+
name = json['Name']
|
|
26
|
+
name.slice(1..-1) if name.start_with?('/')
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def parse_container_status(json)
|
|
30
|
+
json['State']['Status']
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def parse_network_and_port(json, container)
|
|
34
|
+
networks = parse_networks(json)
|
|
35
|
+
return unless networks.is_a? String
|
|
36
|
+
|
|
37
|
+
container.network_setting = Docker2plantuml::NetworkSetting.new(networks)
|
|
38
|
+
container.port_info_list.concat(parse_ports(json))
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def parse_networks(json)
|
|
42
|
+
network_settings = parse_network_settings(json)
|
|
43
|
+
network_settings['Networks'].map { |k, _v| k }.first
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def parse_network_settings(json)
|
|
47
|
+
json['NetworkSettings']
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def parse_ports(json)
|
|
51
|
+
network_settings = parse_network_settings(json)
|
|
52
|
+
create_port_info(network_settings['Ports'])
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def create_port_info(ports)
|
|
56
|
+
ret = ports
|
|
57
|
+
.reject { |_container_port, host_port| host_port.nil? }
|
|
58
|
+
.map do |c_port, h_port|
|
|
59
|
+
h_port.map { |val| Docker2plantuml::PortInfo.new(c_port, val['HostPort']) }
|
|
60
|
+
end
|
|
61
|
+
ret = ret.inject([]) { |list, p| list + p }
|
|
62
|
+
ret.concat(
|
|
63
|
+
ports.select { |_container_port, host_port| host_port.nil? }
|
|
64
|
+
.map { |container_port, _host_port| Docker2plantuml::PortInfo.new(container_port) }
|
|
65
|
+
)
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Docker2plantuml
|
|
4
|
+
class PlantUMLWriter
|
|
5
|
+
I = ' '
|
|
6
|
+
II = ' '
|
|
7
|
+
III = ' '
|
|
8
|
+
|
|
9
|
+
def initialize(container_list)
|
|
10
|
+
@container_list = container_list
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def to_plant_uml
|
|
14
|
+
[
|
|
15
|
+
'@startuml',
|
|
16
|
+
'folder DockerHost {',
|
|
17
|
+
host_ports_to_plant_uml,
|
|
18
|
+
containers_to_plant_uml,
|
|
19
|
+
port_mappings_to_plant_uml,
|
|
20
|
+
'}',
|
|
21
|
+
'@enduml'
|
|
22
|
+
].join("\n")
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def host_ports_to_plant_uml
|
|
26
|
+
@container_list
|
|
27
|
+
.map(&:server_port_list)
|
|
28
|
+
.reject(&:empty?)
|
|
29
|
+
.inject([]) { |list, item| list + item }
|
|
30
|
+
.map { |p| I + "[#{p}]" }
|
|
31
|
+
.join("\n")
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def containers_to_plant_uml
|
|
35
|
+
@container_list
|
|
36
|
+
.map { |c| container_to_plant_uml(c) }
|
|
37
|
+
.join("\n")
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def container_to_plant_uml(container)
|
|
41
|
+
container_name = container.container_name
|
|
42
|
+
ports = ports_to_plant_uml(container)
|
|
43
|
+
[
|
|
44
|
+
I + "cloud [#{container.network_setting.network_name}\\n\\n]{",
|
|
45
|
+
II + "node [#{container_name}\\n]{",
|
|
46
|
+
ports.empty? ? III + '[ ]' : ports,
|
|
47
|
+
II + '}',
|
|
48
|
+
I + '}'
|
|
49
|
+
].join("\n")
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def ports_to_plant_uml(container)
|
|
53
|
+
container_name = container.container_name
|
|
54
|
+
container
|
|
55
|
+
.port_info_list
|
|
56
|
+
.map { |p| III + "[#{container_name}:#{p.container_port}]" }
|
|
57
|
+
.join("\n")
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def port_mappings_to_plant_uml
|
|
61
|
+
@container_list
|
|
62
|
+
.map { |c| port_mapping_to_plant_uml(c) }
|
|
63
|
+
.reject(&:empty?)
|
|
64
|
+
.join("\n")
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def port_mapping_to_plant_uml(container)
|
|
68
|
+
container_name = container.container_name
|
|
69
|
+
return '' if container.port_info_list.empty?
|
|
70
|
+
|
|
71
|
+
container
|
|
72
|
+
.port_info_list
|
|
73
|
+
.select(&:host_port)
|
|
74
|
+
.map { |p| I + port_mapping(container_name, p) }
|
|
75
|
+
.join("\n")
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def port_mapping(c_name, p_info)
|
|
79
|
+
"[#{c_name}:#{p_info.container_port}] -- [#{p_info.host_port}]"
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
data/readme_sample.svg
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentScriptType="application/ecmascript" contentStyleType="text/css" height="358px" preserveAspectRatio="none" style="width:568px;height:358px;" version="1.1" viewBox="0 0 568 358" width="568px" zoomAndPan="magnify"><defs><filter height="300%" id="feo096nt6rv25" width="300%" x="-1" y="-1"><feGaussianBlur result="blurOut" stdDeviation="2.0"/><feColorMatrix in="blurOut" result="blurOut2" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .4 0"/><feOffset dx="4.0" dy="4.0" in="blurOut2" result="blurOut3"/><feBlend in="SourceGraphic" in2="blurOut3" mode="normal"/></filter></defs><g><!--cluster DockerHost--><polygon fill="#FFFFFF" filter="url(#feo096nt6rv25)" points="22,24,120,24,127,46.2969,546,46.2969,546,346,22,346,22,24" style="stroke: #000000; stroke-width: 1.5;"/><line style="stroke: #000000; stroke-width: 1.5;" x1="22" x2="127" y1="46.2969" y2="46.2969"/><text fill="#000000" font-family="sans-serif" font-size="14" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="92" x="26" y="38.9951">DockerHost</text><!--cluster bridge\n\n--><path d="M49,74 C49,71 51,69 54,69 C57,69 59,71 59,74 C59,71 61,69 64,69 C67,69 69,71 69,74 C69,71 71,69 74,69 C77,69 79,71 79,74 C79,71 81,69 84,69 C87,69 89,71 89,74 C89,71 91,69 94,69 C97,69 99,71 99,74 C99,71 101,69 104,69 C107,69 109,71 109,74 C109,71 111,69 114,69 C117,69 119,71 119,74 C119,71 121,69 124,69 C127,69 129,71 129,74 C129,71 131,69 134,69 C137,69 139,71 139,74 C139,71 141,69 144,69 C147,69 149,71 149,74 C149,71 151,69 154,69 C157,69 159,71 159,74 C159,71 161,69 164,69 C167,69 169,71 169,74 C169,71 171,69 174,69 C177,69 179,71 179,74 C179,71 181,69 184,69 C187,69 189,71 189,74 C189,71 191,69 194,69 C197,69 199,71 199,74 C199,71 201,69 204,69 C207,69 209,71 209,74 C209,71 211,69 214,69 C217,69 219,71 219,74 C219,71 221,69 224,69 C227,69 229,71 229,74 C229,71 231,69 234,69 C237,69 239,71 239,74 C239,71 241,69 244,69 C247,69 249,71 249,74 C249,71 251,69 254,69 C257,69 259,71 259,74 C259,71 261,69 264,69 C267,69 269,71 269,74 C269,71 271,69 274,69 C277,69 279,71 279,74 C279,71 281,69 284,69 C287,69 289,71 289,74 C289,71 291,69 294,69 C297,69 299,71 299,74 C299,71 301,69 304,69 C307,69 309,71 309,74 C309,71 311,69 314,69 C317,69 319,71 319,74 C319,71 321,69 324,69 C327,69 329,71 329,74 C329,71 331,69 334,69 C337,69 339,71 339,74 C339,71 341,69 344,69 C347,69 349,71 349,74 C349,71 351,69 354,69 C357,69 359,71 359,74 C359,71 361,69 364,69 C367,69 369,71 369,74 C369,71 371,69 374,69 C377,69 379,71 379,74 C379,71 381,69 384,69 C387,69 389,71 389,74 C389,71 391,69 394,69 C397,69 399,71 399,74 C399,71 401,69 404,69 C407,69 409,71 409,74 C409,71 411,69 414,69 C417,69 419,71 419,74 C419,71 421,69 424,69 C427,69 429,71 429,74 C429,71 431,69 434,69 C437,69 439,71 439,74 C439,71 441,69 444,69 C447,69 449,71 449,74 C449,71 451,69 454,69 C457,69 459,71 459,74 C459,71 461,69 464,69 C467,69 469,71 469,74 C469,71 471,69 474,69 C477,69 479,71 479,74 C479,71 481,69 484,69 C487,69 489,71 489,74 C489,71 491,69 494,69 C497,69 499,71 499,74 C499,71 501,69 504,69 C507,69 509,71 509,74 C509,71 511,69 514,69 C517,69 519,71 519,74 C522,74 524,76 524,79 C524,82 522,84 519,84 C522,84 524,86 524,89 C524,92 522,94 519,94 C522,94 524,96 524,99 C524,102 522,104 519,104 C522,104 524,106 524,109 C524,112 522,114 519,114 C522,114 524,116 524,119 C524,122 522,124 519,124 C522,124 524,126 524,129 C524,132 522,134 519,134 C522,134 524,136 524,139 C524,142 522,144 519,144 C522,144 524,146 524,149 C524,152 522,154 519,154 C522,154 524,156 524,159 C524,162 522,164 519,164 C522,164 524,166 524,169 C524,172 522,174 519,174 C522,174 524,176 524,179 C524,182 522,184 519,184 C522,184 524,186 524,189 C524,192 522,194 519,194 C522,194 524,196 524,199 C524,202 522,204 519,204 C522,204 524,206 524,209 C524,212 522,214 519,214 C522,214 524,216 524,219 C524,222 522,224 519,224 C522,224 524,226 524,229 C524,232 522,234 519,234 C522,234 524,236 524,239 C524,242 522,244 519,244 C522,244 524,246 524,249 C524,252 522,254 519,254 C522,254 524,256 524,259 C524,262 522,264 519,264 C519,267 516,269 514,269 C511,269 509,267 509,264 C509,267 506,269 504,269 C501,269 499,267 499,264 C499,267 496,269 494,269 C491,269 489,267 489,264 C489,267 486,269 484,269 C481,269 479,267 479,264 C479,267 476,269 474,269 C471,269 469,267 469,264 C469,267 466,269 464,269 C461,269 459,267 459,264 C459,267 456,269 454,269 C451,269 449,267 449,264 C449,267 446,269 444,269 C441,269 439,267 439,264 C439,267 436,269 434,269 C431,269 429,267 429,264 C429,267 426,269 424,269 C421,269 419,267 419,264 C419,267 416,269 414,269 C411,269 409,267 409,264 C409,267 406,269 404,269 C401,269 399,267 399,264 C399,267 396,269 394,269 C391,269 389,267 389,264 C389,267 386,269 384,269 C381,269 379,267 379,264 C379,267 376,269 374,269 C371,269 369,267 369,264 C369,267 366,269 364,269 C361,269 359,267 359,264 C359,267 356,269 354,269 C351,269 349,267 349,264 C349,267 346,269 344,269 C341,269 339,267 339,264 C339,267 336,269 334,269 C331,269 329,267 329,264 C329,267 326,269 324,269 C321,269 319,267 319,264 C319,267 316,269 314,269 C311,269 309,267 309,264 C309,267 306,269 304,269 C301,269 299,267 299,264 C299,267 296,269 294,269 C291,269 289,267 289,264 C289,267 286,269 284,269 C281,269 279,267 279,264 C279,267 276,269 274,269 C271,269 269,267 269,264 C269,267 266,269 264,269 C261,269 259,267 259,264 C259,267 256,269 254,269 C251,269 249,267 249,264 C249,267 246,269 244,269 C241,269 239,267 239,264 C239,267 236,269 234,269 C231,269 229,267 229,264 C229,267 226,269 224,269 C221,269 219,267 219,264 C219,267 216,269 214,269 C211,269 209,267 209,264 C209,267 206,269 204,269 C201,269 199,267 199,264 C199,267 196,269 194,269 C191,269 189,267 189,264 C189,267 186,269 184,269 C181,269 179,267 179,264 C179,267 176,269 174,269 C171,269 169,267 169,264 C169,267 166,269 164,269 C161,269 159,267 159,264 C159,267 156,269 154,269 C151,269 149,267 149,264 C149,267 146,269 144,269 C141,269 139,267 139,264 C139,267 136,269 134,269 C131,269 129,267 129,264 C129,267 126,269 124,269 C121,269 119,267 119,264 C119,267 116,269 114,269 C111,269 109,267 109,264 C109,267 106,269 104,269 C101,269 99,267 99,264 C99,267 96,269 94,269 C91,269 89,267 89,264 C89,267 86,269 84,269 C81,269 79,267 79,264 C79,267 76,269 74,269 C71,269 69,267 69,264 C69,267 66,269 64,269 C61,269 59,267 59,264 C59,267 56,269 54,269 C51,269 49,267 49,264 C46,264 44,262 44,259 C44,256 46,254 49,254 C46,254 44,252 44,249 C44,246 46,244 49,244 C46,244 44,242 44,239 C44,236 46,234 49,234 C46,234 44,232 44,229 C44,226 46,224 49,224 C46,224 44,222 44,219 C44,216 46,214 49,214 C46,214 44,212 44,209 C44,206 46,204 49,204 C46,204 44,202 44,199 C44,196 46,194 49,194 C46,194 44,192 44,189 C44,186 46,184 49,184 C46,184 44,182 44,179 C44,176 46,174 49,174 C46,174 44,172 44,169 C44,166 46,164 49,164 C46,164 44,162 44,159 C44,156 46,154 49,154 C46,154 44,152 44,149 C44,146 46,144 49,144 C46,144 44,142 44,139 C44,136 46,134 49,134 C46,134 44,132 44,129 C44,126 46,124 49,124 C46,124 44,122 44,119 C44,116 46,114 49,114 C46,114 44,112 44,109 C44,106 46,104 49,104 C46,104 44,102 44,99 C44,96 46,94 49,94 C46,94 44,92 44,89 C44,86 46,84 49,84 C46,84 44,82 44,79 C44,76 46,74 49,74 " fill="#FFFFFF" filter="url(#feo096nt6rv25)" style="stroke: #000000; stroke-width: 1.5;"/><text fill="#000000" font-family="sans-serif" font-size="14" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="51" x="258.5" y="92.9951">bridge</text><text fill="#000000" font-family="sans-serif" font-size="14" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="0" x="286.5" y="109.292"/><text fill="#000000" font-family="sans-serif" font-size="14" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="0" x="286.5" y="125.5889"/><!--cluster http-server\n--><polygon fill="#FFFFFF" filter="url(#feo096nt6rv25)" points="70,152,80,142,248,142,248,240,238,250,70,250,70,152" style="stroke: #000000; stroke-width: 1.5;"/><line style="stroke: #000000; stroke-width: 1.5;" x1="238" x2="247" y1="152" y2="143"/><line style="stroke: #000000; stroke-width: 1.5;" x1="70" x2="238" y1="152" y2="152"/><line style="stroke: #000000; stroke-width: 1.5;" x1="238" x2="238" y1="152" y2="250"/><text fill="#000000" font-family="sans-serif" font-size="14" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="90" x="110" y="167.9951">http-server</text><text fill="#000000" font-family="sans-serif" font-size="14" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="0" x="157.5" y="184.292"/><!--cluster mongo-server\n--><polygon fill="#FFFFFF" filter="url(#feo096nt6rv25)" points="272,152,282,142,498,142,498,240,488,250,272,250,272,152" style="stroke: #000000; stroke-width: 1.5;"/><line style="stroke: #000000; stroke-width: 1.5;" x1="488" x2="497" y1="152" y2="143"/><line style="stroke: #000000; stroke-width: 1.5;" x1="272" x2="488" y1="152" y2="152"/><line style="stroke: #000000; stroke-width: 1.5;" x1="488" x2="488" y1="152" y2="250"/><text fill="#000000" font-family="sans-serif" font-size="14" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="112" x="325" y="167.9951">mongo-server</text><text fill="#000000" font-family="sans-serif" font-size="14" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="0" x="383.5" y="184.292"/><!--entity 8080--><rect fill="#FEFECE" filter="url(#feo096nt6rv25)" height="36.2969" style="stroke: #A80036; stroke-width: 1.5;" width="56" x="131" y="294"/><rect fill="#FEFECE" height="5" style="stroke: #A80036; stroke-width: 1.5;" width="10" x="126" y="299"/><rect fill="#FEFECE" height="5" style="stroke: #A80036; stroke-width: 1.5;" width="10" x="126" y="320.2969"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="36" x="141" y="316.9951">8080</text><!--entity 27017--><rect fill="#FEFECE" filter="url(#feo096nt6rv25)" height="36.2969" style="stroke: #A80036; stroke-width: 1.5;" width="65" x="352.5" y="294"/><rect fill="#FEFECE" height="5" style="stroke: #A80036; stroke-width: 1.5;" width="10" x="347.5" y="299"/><rect fill="#FEFECE" height="5" style="stroke: #A80036; stroke-width: 1.5;" width="10" x="347.5" y="320.2969"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="45" x="362.5" y="316.9951">27017</text><!--entity http-server:80/tcp--><rect fill="#FEFECE" filter="url(#feo096nt6rv25)" height="36.2969" style="stroke: #A80036; stroke-width: 1.5;" width="146" x="86" y="198"/><rect fill="#FEFECE" height="5" style="stroke: #A80036; stroke-width: 1.5;" width="10" x="81" y="203"/><rect fill="#FEFECE" height="5" style="stroke: #A80036; stroke-width: 1.5;" width="10" x="81" y="224.2969"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="126" x="96" y="220.9951">http-server:80/tcp</text><!--entity mongo-server:27017/tcp--><rect fill="#FEFECE" filter="url(#feo096nt6rv25)" height="36.2969" style="stroke: #A80036; stroke-width: 1.5;" width="194" x="288" y="198"/><rect fill="#FEFECE" height="5" style="stroke: #A80036; stroke-width: 1.5;" width="10" x="283" y="203"/><rect fill="#FEFECE" height="5" style="stroke: #A80036; stroke-width: 1.5;" width="10" x="283" y="224.2969"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="174" x="298" y="220.9951">mongo-server:27017/tcp</text><!--link http-server:80/tcp to 8080--><path d="M159,234.241 C159,251.202 159,276.9455 159,293.8683 " fill="none" id="http-server:80/tcp-8080" style="stroke: #A80036; stroke-width: 1.0;"/><!--link mongo-server:27017/tcp to 27017--><path d="M385,234.241 C385,251.202 385,276.9455 385,293.8683 " fill="none" id="mongo-server:27017/tcp-27017" style="stroke: #A80036; stroke-width: 1.0;"/><!--
|
|
2
|
+
@startuml
|
|
3
|
+
|
|
4
|
+
folder DockerHost {
|
|
5
|
+
[8080]
|
|
6
|
+
[27017]
|
|
7
|
+
cloud [bridge\n\n]{
|
|
8
|
+
node [http-server\n]{
|
|
9
|
+
[http-server:80/tcp]
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
cloud [bridge\n\n]{
|
|
13
|
+
node [mongo-server\n]{
|
|
14
|
+
[mongo-server:27017/tcp]
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
[http-server:80/tcp] - - [8080]
|
|
18
|
+
[mongo-server:27017/tcp] - - [27017]
|
|
19
|
+
}
|
|
20
|
+
@enduml
|
|
21
|
+
|
|
22
|
+
PlantUML version 1.2018.15beta2(Unknown compile time)
|
|
23
|
+
(GPL source distribution)
|
|
24
|
+
Java Runtime: Java(TM) SE Runtime Environment
|
|
25
|
+
JVM: Java HotSpot(TM) 64-Bit Server VM
|
|
26
|
+
Java Version: 1.7.0_25-b15
|
|
27
|
+
Operating System: Linux
|
|
28
|
+
Default Encoding: UTF-8
|
|
29
|
+
Language: en
|
|
30
|
+
Country: US
|
|
31
|
+
--></g></svg>
|
metadata
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: docker2plantuml
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- unapon
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: exe
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2018-12-29 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: bundler
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '1.16'
|
|
20
|
+
type: :development
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '1.16'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: rake
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '10.0'
|
|
34
|
+
type: :development
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - "~>"
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '10.0'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: rspec
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - "~>"
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '3.0'
|
|
48
|
+
type: :development
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - "~>"
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '3.0'
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: rubocop
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - "~>"
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: 0.61.1
|
|
62
|
+
type: :development
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - "~>"
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: 0.61.1
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: simplecov
|
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - "~>"
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: 0.16.1
|
|
76
|
+
type: :development
|
|
77
|
+
prerelease: false
|
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - "~>"
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: 0.16.1
|
|
83
|
+
description: Generate PlantUML from "docker inspect" command.
|
|
84
|
+
email:
|
|
85
|
+
- unapon.dev@gmail.com
|
|
86
|
+
executables:
|
|
87
|
+
- docker2plantuml
|
|
88
|
+
extensions: []
|
|
89
|
+
extra_rdoc_files: []
|
|
90
|
+
files:
|
|
91
|
+
- ".circleci/config.yml"
|
|
92
|
+
- ".gitignore"
|
|
93
|
+
- ".rspec"
|
|
94
|
+
- ".rubocop.yml"
|
|
95
|
+
- ".travis.yml"
|
|
96
|
+
- CODE_OF_CONDUCT.md
|
|
97
|
+
- Gemfile
|
|
98
|
+
- LICENSE.txt
|
|
99
|
+
- README.md
|
|
100
|
+
- Rakefile
|
|
101
|
+
- bin/console
|
|
102
|
+
- bin/setup
|
|
103
|
+
- docker2plantuml.gemspec
|
|
104
|
+
- exe/docker2plantuml
|
|
105
|
+
- lib/docker2plantuml.rb
|
|
106
|
+
- lib/docker2plantuml/command.rb
|
|
107
|
+
- lib/docker2plantuml/model.rb
|
|
108
|
+
- lib/docker2plantuml/parser.rb
|
|
109
|
+
- lib/docker2plantuml/version.rb
|
|
110
|
+
- lib/docker2plantuml/writer.rb
|
|
111
|
+
- readme_sample.svg
|
|
112
|
+
homepage: https://github.com/unapon/docker2plantuml
|
|
113
|
+
licenses:
|
|
114
|
+
- MIT
|
|
115
|
+
metadata: {}
|
|
116
|
+
post_install_message:
|
|
117
|
+
rdoc_options: []
|
|
118
|
+
require_paths:
|
|
119
|
+
- lib
|
|
120
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
121
|
+
requirements:
|
|
122
|
+
- - ">="
|
|
123
|
+
- !ruby/object:Gem::Version
|
|
124
|
+
version: '0'
|
|
125
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
126
|
+
requirements:
|
|
127
|
+
- - ">="
|
|
128
|
+
- !ruby/object:Gem::Version
|
|
129
|
+
version: '0'
|
|
130
|
+
requirements: []
|
|
131
|
+
rubyforge_project:
|
|
132
|
+
rubygems_version: 2.7.3
|
|
133
|
+
signing_key:
|
|
134
|
+
specification_version: 4
|
|
135
|
+
summary: Generate PlantUML from "docker inspect" command.
|
|
136
|
+
test_files: []
|