Merge pull request #15 from compose-viz/dev
feat: implement parser and graph generator
This commit is contained in:
commit
8068121a4f
104 changed files with 1606 additions and 1975 deletions
5
.github/workflows/cd.yml
vendored
5
.github/workflows/cd.yml
vendored
|
@ -10,8 +10,9 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Build and Publish to PyPi
|
- name: Build and Publish to PyPi
|
||||||
uses: JRubics/poetry-publish@v1.10
|
uses: JRubics/poetry-publish@v1.10
|
||||||
with:
|
with:
|
||||||
pypi_token: ${{ secrets.PYPI_TOKEN }}
|
pypi_token: ${{ secrets.PYPI_TOKEN }}
|
||||||
|
extra_build_dependency_packages: "graphviz"
|
||||||
|
|
96
.github/workflows/ci.yml
vendored
96
.github/workflows/ci.yml
vendored
|
@ -12,81 +12,31 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
|
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Switch to Current Branch
|
- name: Switch to Current Branch
|
||||||
run: git checkout ${{ env.BRANCH }}
|
run: git checkout ${{ env.BRANCH }}
|
||||||
|
|
||||||
|
- run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y graphviz
|
||||||
|
|
||||||
|
- name: Validate Test Files
|
||||||
|
run: |
|
||||||
|
docker compose -f tests/ymls/builds/docker-compose.yml config -q
|
||||||
|
docker compose -f tests/ymls/depends_on/docker-compose.yml config -q
|
||||||
|
docker compose -f tests/ymls/extends/docker-compose.yml config -q
|
||||||
|
docker compose -f tests/ymls/links/docker-compose.yml config -q
|
||||||
|
docker compose -f tests/ymls/networks/docker-compose.yml config -q
|
||||||
|
docker compose -f tests/ymls/ports/docker-compose.yml config -q
|
||||||
|
docker compose -f tests/ymls/volumes/docker-compose.yml config -q
|
||||||
|
docker compose -f examples/full-stack-node-app/docker-compose.yml config -q
|
||||||
|
docker compose -f examples/non-normative/docker-compose.yml config -q
|
||||||
|
|
||||||
- name: Setup Python 3.10.4
|
- name: Setup Python 3.10.4
|
||||||
uses: actions/setup-python@v3
|
uses: actions/setup-python@v3
|
||||||
with:
|
with:
|
||||||
python-version: '3.10.4'
|
python-version: '3.10.4'
|
||||||
|
|
||||||
- name: Validate Test Files
|
|
||||||
run: |
|
|
||||||
docker-compose -f tests/in/000001.yaml config -q
|
|
||||||
docker-compose -f tests/in/000010.yaml config -q
|
|
||||||
docker-compose -f tests/in/000011.yaml config -q
|
|
||||||
docker-compose -f tests/in/000100.yaml config -q
|
|
||||||
docker-compose -f tests/in/000101.yaml config -q
|
|
||||||
docker-compose -f tests/in/000110.yaml config -q
|
|
||||||
docker-compose -f tests/in/000111.yaml config -q
|
|
||||||
docker-compose -f tests/in/001000.yaml config -q
|
|
||||||
docker-compose -f tests/in/001001.yaml config -q
|
|
||||||
docker-compose -f tests/in/001010.yaml config -q
|
|
||||||
docker-compose -f tests/in/001011.yaml config -q
|
|
||||||
docker-compose -f tests/in/001100.yaml config -q
|
|
||||||
docker-compose -f tests/in/001101.yaml config -q
|
|
||||||
docker-compose -f tests/in/001110.yaml config -q
|
|
||||||
docker-compose -f tests/in/001111.yaml config -q
|
|
||||||
docker-compose -f tests/in/010000.yaml config -q
|
|
||||||
docker-compose -f tests/in/010001.yaml config -q
|
|
||||||
docker-compose -f tests/in/010010.yaml config -q
|
|
||||||
docker-compose -f tests/in/010011.yaml config -q
|
|
||||||
docker-compose -f tests/in/010100.yaml config -q
|
|
||||||
docker-compose -f tests/in/010101.yaml config -q
|
|
||||||
docker-compose -f tests/in/010110.yaml config -q
|
|
||||||
docker-compose -f tests/in/010111.yaml config -q
|
|
||||||
docker-compose -f tests/in/011000.yaml config -q
|
|
||||||
docker-compose -f tests/in/011001.yaml config -q
|
|
||||||
docker-compose -f tests/in/011010.yaml config -q
|
|
||||||
docker-compose -f tests/in/011011.yaml config -q
|
|
||||||
docker-compose -f tests/in/011100.yaml config -q
|
|
||||||
docker-compose -f tests/in/011101.yaml config -q
|
|
||||||
docker-compose -f tests/in/011110.yaml config -q
|
|
||||||
docker-compose -f tests/in/011111.yaml config -q
|
|
||||||
docker-compose -f tests/in/100000.yaml config -q
|
|
||||||
docker-compose -f tests/in/100001.yaml config -q
|
|
||||||
docker-compose -f tests/in/100010.yaml config -q
|
|
||||||
docker-compose -f tests/in/100011.yaml config -q
|
|
||||||
docker-compose -f tests/in/100100.yaml config -q
|
|
||||||
docker-compose -f tests/in/100101.yaml config -q
|
|
||||||
docker-compose -f tests/in/100110.yaml config -q
|
|
||||||
docker-compose -f tests/in/100111.yaml config -q
|
|
||||||
docker-compose -f tests/in/101000.yaml config -q
|
|
||||||
docker-compose -f tests/in/101001.yaml config -q
|
|
||||||
docker-compose -f tests/in/101010.yaml config -q
|
|
||||||
docker-compose -f tests/in/101011.yaml config -q
|
|
||||||
docker-compose -f tests/in/101100.yaml config -q
|
|
||||||
docker-compose -f tests/in/101101.yaml config -q
|
|
||||||
docker-compose -f tests/in/101110.yaml config -q
|
|
||||||
docker-compose -f tests/in/101111.yaml config -q
|
|
||||||
docker-compose -f tests/in/110000.yaml config -q
|
|
||||||
docker-compose -f tests/in/110001.yaml config -q
|
|
||||||
docker-compose -f tests/in/110010.yaml config -q
|
|
||||||
docker-compose -f tests/in/110011.yaml config -q
|
|
||||||
docker-compose -f tests/in/110100.yaml config -q
|
|
||||||
docker-compose -f tests/in/110101.yaml config -q
|
|
||||||
docker-compose -f tests/in/110110.yaml config -q
|
|
||||||
docker-compose -f tests/in/110111.yaml config -q
|
|
||||||
docker-compose -f tests/in/111000.yaml config -q
|
|
||||||
docker-compose -f tests/in/111001.yaml config -q
|
|
||||||
docker-compose -f tests/in/111010.yaml config -q
|
|
||||||
docker-compose -f tests/in/111011.yaml config -q
|
|
||||||
docker-compose -f tests/in/111100.yaml config -q
|
|
||||||
docker-compose -f tests/in/111101.yaml config -q
|
|
||||||
docker-compose -f tests/in/111110.yaml config -q
|
|
||||||
docker-compose -f tests/in/111111.yaml config -q
|
|
||||||
|
|
||||||
- name: Setup Poetry
|
- name: Setup Poetry
|
||||||
uses: Gr1N/setup-poetry@v7
|
uses: Gr1N/setup-poetry@v7
|
||||||
with:
|
with:
|
||||||
|
@ -96,6 +46,10 @@ jobs:
|
||||||
run: |
|
run: |
|
||||||
poetry install --no-root
|
poetry install --no-root
|
||||||
|
|
||||||
- name: Validate Custom Input File
|
- name: Execute pre-commit
|
||||||
run: |
|
run: |
|
||||||
poetry run python -m pytest
|
poetry run python -m pre_commit run --all-files --show-diff-on-failure
|
||||||
|
|
||||||
|
- name: Run Pytest
|
||||||
|
run: |
|
||||||
|
poetry run python -m pytest --cov=compose_viz tests/ --tb=short
|
||||||
|
|
14
.github/workflows/release-tagged-version.yml
vendored
14
.github/workflows/release-tagged-version.yml
vendored
|
@ -18,15 +18,19 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
|
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Switch to Current Branch
|
- name: Switch to Current Branch
|
||||||
run: git checkout ${{ env.BRANCH }}
|
run: git checkout ${{ env.BRANCH }}
|
||||||
|
|
||||||
|
- run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y graphviz
|
||||||
|
|
||||||
- name: Setup Python 3.10.4
|
- name: Setup Python 3.10.4
|
||||||
uses: actions/setup-python@v3
|
uses: actions/setup-python@v3
|
||||||
with:
|
with:
|
||||||
python-version: '3.10.4'
|
python-version: '3.10.4'
|
||||||
|
|
||||||
- name: Setup Poetry
|
- name: Setup Poetry
|
||||||
uses: Gr1N/setup-poetry@v7
|
uses: Gr1N/setup-poetry@v7
|
||||||
with:
|
with:
|
||||||
|
@ -34,7 +38,7 @@ jobs:
|
||||||
- run: |
|
- run: |
|
||||||
poetry install --no-root
|
poetry install --no-root
|
||||||
poetry build
|
poetry build
|
||||||
|
|
||||||
- name: "Release Tagged Version"
|
- name: "Release Tagged Version"
|
||||||
uses: "marvinpinto/action-automatic-releases@latest"
|
uses: "marvinpinto/action-automatic-releases@latest"
|
||||||
with:
|
with:
|
||||||
|
@ -42,4 +46,4 @@ jobs:
|
||||||
prerelease: false
|
prerelease: false
|
||||||
files: |
|
files: |
|
||||||
LICENSE
|
LICENSE
|
||||||
dist/**
|
dist/**
|
||||||
|
|
5
.gitignore
vendored
5
.gitignore
vendored
|
@ -158,4 +158,7 @@ cython_debug/
|
||||||
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
||||||
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||||
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||||
#.idea/
|
#.idea/
|
||||||
|
|
||||||
|
*.png
|
||||||
|
!examples/**/*.png
|
||||||
|
|
38
.pre-commit-config.yaml
Normal file
38
.pre-commit-config.yaml
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
exclude: |
|
||||||
|
(?x)^(
|
||||||
|
README.md|
|
||||||
|
LICENSE|
|
||||||
|
tests/ymls/others/
|
||||||
|
)
|
||||||
|
repos:
|
||||||
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
|
rev: v4.2.0
|
||||||
|
hooks:
|
||||||
|
- id: check-yaml
|
||||||
|
- id: end-of-file-fixer
|
||||||
|
- id: trailing-whitespace
|
||||||
|
- repo: https://github.com/pycqa/flake8
|
||||||
|
rev: 4.0.1
|
||||||
|
hooks:
|
||||||
|
- id: flake8
|
||||||
|
args:
|
||||||
|
- "--max-line-length=120"
|
||||||
|
- repo: https://github.com/pycqa/isort
|
||||||
|
rev: 5.10.1
|
||||||
|
hooks:
|
||||||
|
- id: isort
|
||||||
|
- repo: https://github.com/psf/black
|
||||||
|
rev: 22.3.0
|
||||||
|
hooks:
|
||||||
|
- id: black
|
||||||
|
args: # arguments to configure black
|
||||||
|
- --line-length=120
|
||||||
|
- repo: local
|
||||||
|
hooks:
|
||||||
|
- id: pyright
|
||||||
|
name: pyright
|
||||||
|
entry: pyright
|
||||||
|
language: node
|
||||||
|
pass_filenames: false
|
||||||
|
types: [python]
|
||||||
|
additional_dependencies: ['pyright@1.1.247']
|
40
README.md
40
README.md
|
@ -38,6 +38,8 @@
|
||||||
<li>
|
<li>
|
||||||
<a href="#getting-started">Getting Started</a>
|
<a href="#getting-started">Getting Started</a>
|
||||||
<ul>
|
<ul>
|
||||||
|
<li><a href="#prerequisities">Prerequisities</a></li>
|
||||||
|
<li><a href="#installation">Installation</a></li>
|
||||||
<li><a href="#usage">Usage</a></li>
|
<li><a href="#usage">Usage</a></li>
|
||||||
<li><a href="#options">Options</a></li>
|
<li><a href="#options">Options</a></li>
|
||||||
<li><a href="#example">Example</a></li>
|
<li><a href="#example">Example</a></li>
|
||||||
|
@ -54,7 +56,9 @@
|
||||||
|
|
||||||
## About The Project
|
## About The Project
|
||||||
|
|
||||||
`compose-viz` is a [docker-compose](https://github.com/docker/compose)/[podman-compose](https://github.com/containers/podman-compose) graph visualization tool that allows you to gernerate graph in [DOT](https://graphviz.org/doc/info/lang.html) format or `.png`.
|
`compose-viz` is a compose file visualization tool that supports [compose-spec](https://github.com/compose-spec/compose-spec/blob/master/spec.md) and allows you to gernerate graph in [DOT](https://graphviz.org/doc/info/lang.html) format or `.png`.
|
||||||
|
|
||||||
|
If you are looking for a compose file vizualization tool, and you are using one of the [compose-spec](https://github.com/compose-spec/compose-spec/blob/master/spec.md) implementations (e.g. [docker-compose](https://github.com/docker/compose)/[podman-compose](https://github.com/containers/podman-compose)), then `compose-viz` is a great choice for you.
|
||||||
|
|
||||||
<p align="right">(<a href="#top">back to top</a>)</p>
|
<p align="right">(<a href="#top">back to top</a>)</p>
|
||||||
|
|
||||||
|
@ -62,20 +66,40 @@
|
||||||
|
|
||||||
## Getting Started
|
## Getting Started
|
||||||
|
|
||||||
|
### Prerequisities
|
||||||
|
|
||||||
|
#### Graphviz
|
||||||
|
|
||||||
|
If you want to generate PNG (which is the default option), you need to install [Graphviz](https://graphviz.org/download/).
|
||||||
|
|
||||||
|
### Installation
|
||||||
|
|
||||||
|
#### Using `pip`
|
||||||
|
|
||||||
|
`pip install compose-viz`
|
||||||
|
|
||||||
|
#### Using `.whl`
|
||||||
|
|
||||||
|
See [releases](https://github.com/compose-viz/compose-viz/releases).
|
||||||
|
|
||||||
### Usage
|
### Usage
|
||||||
|
|
||||||
`python3 compose-viz.py [OPTIONS] [input-file]`
|
`cpv [OPTIONS] INPUT_PATH`
|
||||||
|
|
||||||
### Options
|
### Options
|
||||||
|
|
||||||
| Option | Necessity | Description | Default Value |
|
| Option | Description |
|
||||||
| ----------------------------- | --------- | ----------------- | --------------- |
|
| ------------------------ | ------------------------------------------------------------------------------ |
|
||||||
| `-o --output-file` | Optional | Output file path. | `./compose.png` |
|
| `-o, --output-path` | Output path for the generated visualization file. [default: ./compose-viz.png] |
|
||||||
| `-m --output-format=DOT, PNG` | Optional | Output format. | PNG |
|
| `-m, --format [PNG,DOT]` | Output format for the generated visualization file. [default: PNG] |
|
||||||
|
| `-v, --version` | Show the version of compose-viz. |
|
||||||
|
| `--help` | Show help and exit. |
|
||||||
|
|
||||||
### Example
|
### Example
|
||||||
|
|
||||||
`python3 compose-viz.py docker-compose.yaml`
|
`cpv -o .\examples\full-stack-node-app\compose-viz.png .\examples\full-stack-node-app\docker-compose.yml`
|
||||||
|
|
||||||
|
[Here](https://github.com/compose-viz/compose-viz/blob/main/examples/full-stack-node-app/compose-viz.png) is the result.
|
||||||
|
|
||||||
<p align="right">(<a href="#top">back to top</a>)</p>
|
<p align="right">(<a href="#top">back to top</a>)</p>
|
||||||
|
|
||||||
|
@ -83,7 +107,7 @@
|
||||||
|
|
||||||
## Roadmap
|
## Roadmap
|
||||||
|
|
||||||
- [ ] Support [podman-compose](https://github.com/containers/podman-compose).
|
- [ ] Support more vizualization components.
|
||||||
|
|
||||||
See the [open issues](https://github.com/compose-viz/compose-viz/issues)
|
See the [open issues](https://github.com/compose-viz/compose-viz/issues)
|
||||||
for a full list of proposed features (and known issues).
|
for a full list of proposed features (and known issues).
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
from compose_viz.cli import start_cli
|
from compose_viz.cli import start_cli
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
start_cli()
|
start_cli()
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
import typer
|
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
|
import typer
|
||||||
|
|
||||||
from compose_viz import __app_name__, __version__
|
from compose_viz import __app_name__, __version__
|
||||||
|
from compose_viz.graph import Graph
|
||||||
from compose_viz.parser import Parser
|
from compose_viz.parser import Parser
|
||||||
|
|
||||||
|
|
||||||
|
@ -27,26 +30,26 @@ def _version_callback(value: bool) -> None:
|
||||||
@app.callback()
|
@app.callback()
|
||||||
def compose_viz(
|
def compose_viz(
|
||||||
input_path: str,
|
input_path: str,
|
||||||
output_path: Optional[str] = typer.Option(
|
output_path: str = typer.Option(
|
||||||
None,
|
"./compose-viz.png",
|
||||||
"--output_path",
|
"--output-path",
|
||||||
"-o",
|
"-o",
|
||||||
help="Output path for the generated visualization.",
|
help="Output path for the generated visualization file.",
|
||||||
),
|
),
|
||||||
format: VisualizationFormats = typer.Option(
|
format: VisualizationFormats = typer.Option(
|
||||||
"PNG",
|
"PNG",
|
||||||
"--format",
|
"--format",
|
||||||
"-m",
|
"-m",
|
||||||
help="Output format for the generated visualization.",
|
help="Output format for the generated visualization file.",
|
||||||
),
|
),
|
||||||
_: Optional[bool] = typer.Option(
|
_: Optional[bool] = typer.Option(
|
||||||
None,
|
None,
|
||||||
"--version",
|
"--version",
|
||||||
"-v",
|
"-v",
|
||||||
help="Show the version of compose_viz.",
|
help="Show the version of compose-viz.",
|
||||||
callback=_version_callback,
|
callback=_version_callback,
|
||||||
is_eager=True,
|
is_eager=True,
|
||||||
)
|
),
|
||||||
) -> None:
|
) -> None:
|
||||||
parser = Parser()
|
parser = Parser()
|
||||||
compose = parser.parse(input_path)
|
compose = parser.parse(input_path)
|
||||||
|
@ -54,8 +57,10 @@ def compose_viz(
|
||||||
if compose:
|
if compose:
|
||||||
typer.echo(f"Successfully parsed {input_path}")
|
typer.echo(f"Successfully parsed {input_path}")
|
||||||
|
|
||||||
|
Graph(compose, output_path).render(format)
|
||||||
|
|
||||||
raise typer.Exit()
|
raise typer.Exit()
|
||||||
|
|
||||||
|
|
||||||
def start_cli() -> None:
|
def start_cli() -> None:
|
||||||
app(prog_name=__app_name__)
|
app(prog_name="cpv")
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
from compose_viz.service import Service
|
from compose_viz.service import Service
|
||||||
|
|
||||||
|
|
||||||
class Compose:
|
class Compose:
|
||||||
def __init__(self, services: List[Service]) -> None:
|
def __init__(self, services: List[Service]) -> None:
|
||||||
self.services = services
|
self._services = services
|
||||||
|
|
||||||
def extract_networks(self) -> List[str]:
|
@property
|
||||||
raise NotImplementedError
|
def services(self):
|
||||||
|
return self._services
|
||||||
|
|
15
compose_viz/extends.py
Normal file
15
compose_viz/extends.py
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
|
||||||
|
class Extends:
|
||||||
|
def __init__(self, service_name: str, from_file: Optional[str] = None):
|
||||||
|
self._service_name = service_name
|
||||||
|
self._from_file = from_file
|
||||||
|
|
||||||
|
@property
|
||||||
|
def service_name(self):
|
||||||
|
return self._service_name
|
||||||
|
|
||||||
|
@property
|
||||||
|
def from_file(self):
|
||||||
|
return self._from_file
|
92
compose_viz/graph.py
Normal file
92
compose_viz/graph.py
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
import graphviz
|
||||||
|
|
||||||
|
from compose_viz.compose import Compose
|
||||||
|
|
||||||
|
|
||||||
|
def apply_vertex_style(type) -> dict:
|
||||||
|
style = {
|
||||||
|
"service": {
|
||||||
|
"shape": "component",
|
||||||
|
},
|
||||||
|
"volume": {
|
||||||
|
"shape": "folder",
|
||||||
|
},
|
||||||
|
"network": {
|
||||||
|
"shape": "pentagon",
|
||||||
|
},
|
||||||
|
"port": {
|
||||||
|
"shape": "circle",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return style[type]
|
||||||
|
|
||||||
|
|
||||||
|
def apply_edge_style(type) -> dict:
|
||||||
|
style = {
|
||||||
|
"ports": {
|
||||||
|
"style": "solid",
|
||||||
|
"dir": "both",
|
||||||
|
},
|
||||||
|
"links": {
|
||||||
|
"style": "solid",
|
||||||
|
},
|
||||||
|
"volumes": {
|
||||||
|
"style": "dashed",
|
||||||
|
"dir": "both",
|
||||||
|
},
|
||||||
|
"depends_on": {
|
||||||
|
"style": "dotted",
|
||||||
|
},
|
||||||
|
"extends": {
|
||||||
|
"dir": "both",
|
||||||
|
"arrowhead": "inv",
|
||||||
|
"arrowtail": "dot",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return style[type]
|
||||||
|
|
||||||
|
|
||||||
|
class Graph:
|
||||||
|
def __init__(self, compose: Compose, filename: str) -> None:
|
||||||
|
self.dot = graphviz.Digraph()
|
||||||
|
self.dot.attr("graph", background="#ffffff", pad="0.5", ratio="fill")
|
||||||
|
self.compose = compose
|
||||||
|
self.filename = filename
|
||||||
|
|
||||||
|
def validate_name(self, name: str) -> str:
|
||||||
|
# graphviz does not allow ':' in node name
|
||||||
|
transTable = name.maketrans({":": ""})
|
||||||
|
return name.translate(transTable)
|
||||||
|
|
||||||
|
def add_vertex(self, name: str, type: str, lable: Optional[str] = None) -> None:
|
||||||
|
self.dot.node(self.validate_name(name), lable, **apply_vertex_style(type))
|
||||||
|
|
||||||
|
def add_edge(self, head: str, tail: str, type: str, lable: Optional[str] = None) -> None:
|
||||||
|
self.dot.edge(self.validate_name(head), self.validate_name(tail), lable, **apply_edge_style(type))
|
||||||
|
|
||||||
|
def render(self, format: str, cleanup: bool = True) -> None:
|
||||||
|
for service in self.compose.services:
|
||||||
|
if service.image is not None:
|
||||||
|
self.add_vertex(service.name, "service", lable=f"{service.name}\n({service.image})")
|
||||||
|
if service.extends is not None:
|
||||||
|
self.add_vertex(service.name, "service", lable=f"{service.name}\n")
|
||||||
|
self.add_edge(service.extends.service_name, service.name, "extends")
|
||||||
|
for network in service.networks:
|
||||||
|
self.add_vertex(network, "network", lable=f"net:{network}")
|
||||||
|
self.add_edge(service.name, network, "links")
|
||||||
|
for volume in service.volumes:
|
||||||
|
self.add_vertex(volume.source, "volume")
|
||||||
|
self.add_edge(service.name, volume.source, "volumes", lable=volume.target)
|
||||||
|
for port in service.ports:
|
||||||
|
self.add_vertex(port.host_port, "port", lable=port.host_port)
|
||||||
|
self.add_edge(port.host_port, service.name, "ports", lable=port.container_port)
|
||||||
|
for link in service.links:
|
||||||
|
self.add_edge(link.split(":")[0], service.name, "links", link.split(":")[1])
|
||||||
|
for depends_on in service.depends_on:
|
||||||
|
self.add_edge(service.name, depends_on, "depends_on")
|
||||||
|
|
||||||
|
self.dot.render(outfile=self.filename, format=format, cleanup=cleanup)
|
|
@ -1,4 +1,12 @@
|
||||||
from compose_viz.compose import Compose
|
import re
|
||||||
|
from typing import Dict, List, Optional
|
||||||
|
|
||||||
|
from ruamel.yaml import YAML
|
||||||
|
|
||||||
|
from compose_viz.compose import Compose, Service
|
||||||
|
from compose_viz.extends import Extends
|
||||||
|
from compose_viz.port import Port, Protocol
|
||||||
|
from compose_viz.volume import Volume, VolumeType
|
||||||
|
|
||||||
|
|
||||||
class Parser:
|
class Parser:
|
||||||
|
@ -6,5 +14,216 @@ class Parser:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def parse(self, file_path: str) -> Compose:
|
def parse(self, file_path: str) -> Compose:
|
||||||
# validate input file using `docker-compose config -q sys.argv[1]` first
|
# load the yaml file
|
||||||
raise NotImplementedError
|
with open(file_path, "r") as f:
|
||||||
|
try:
|
||||||
|
yaml = YAML(typ="safe", pure=True)
|
||||||
|
yaml_data = yaml.load(f)
|
||||||
|
except Exception as e:
|
||||||
|
raise RuntimeError(f"Error parsing file '{file_path}': {e}")
|
||||||
|
# validate the yaml file
|
||||||
|
if not yaml_data:
|
||||||
|
raise RuntimeError("Empty yaml file, aborting.")
|
||||||
|
if not yaml_data.get("services"):
|
||||||
|
raise RuntimeError("No services found, aborting.")
|
||||||
|
|
||||||
|
# parse services data into Service objects
|
||||||
|
services = self.parse_service_data(yaml_data["services"])
|
||||||
|
|
||||||
|
# create Compose object
|
||||||
|
compose = Compose(services)
|
||||||
|
|
||||||
|
return compose
|
||||||
|
|
||||||
|
def parse_service_data(self, services_yaml_data: Dict[str, dict]) -> List[Service]:
|
||||||
|
services: List[Service] = []
|
||||||
|
for service, service_name in zip(services_yaml_data.values(), services_yaml_data.keys()):
|
||||||
|
|
||||||
|
service_image: Optional[str] = None
|
||||||
|
if service.get("build"):
|
||||||
|
if type(service["build"]) is str:
|
||||||
|
service_image = f"build from '{service['build']}'"
|
||||||
|
elif type(service["build"]) is dict:
|
||||||
|
if service["build"].get("context") and service["build"].get("dockerfile"):
|
||||||
|
service_image = (
|
||||||
|
f"build from '{service['build']['context']}' using '{service['build']['dockerfile']}'"
|
||||||
|
)
|
||||||
|
elif service["build"].get("context"):
|
||||||
|
service_image = f"build from '{service['build']['context']}'"
|
||||||
|
if service.get("image"):
|
||||||
|
if service_image:
|
||||||
|
service_image += ", image: " + service["image"]
|
||||||
|
else:
|
||||||
|
service_image = service["image"]
|
||||||
|
|
||||||
|
service_networks: List[str] = []
|
||||||
|
if service.get("networks"):
|
||||||
|
if type(service["networks"]) is list:
|
||||||
|
service_networks = service["networks"]
|
||||||
|
elif type(service["networks"]) is dict:
|
||||||
|
service_networks = list(service["networks"].keys())
|
||||||
|
|
||||||
|
service_extends: Optional[Extends] = None
|
||||||
|
if service.get("extends"):
|
||||||
|
assert type(service["extends"]) is dict, "Invalid extends format, aborting."
|
||||||
|
assert service["extends"]["service"], "Missing extends service, aborting."
|
||||||
|
extend_service_name = str(service["extends"]["service"])
|
||||||
|
|
||||||
|
extend_from_file: Optional[str] = None
|
||||||
|
if service["extends"].get("file"):
|
||||||
|
assert service["extends"]["file"], "Missing extends file, aborting."
|
||||||
|
extend_from_file = str(service["extends"]["file"])
|
||||||
|
|
||||||
|
service_extends = Extends(service_name=extend_service_name, from_file=extend_from_file)
|
||||||
|
|
||||||
|
service_ports: List[Port] = []
|
||||||
|
if service.get("ports"):
|
||||||
|
assert type(service["ports"]) is list
|
||||||
|
for port_data in service["ports"]:
|
||||||
|
if type(port_data) is dict:
|
||||||
|
# define a nested function to limit variable scope
|
||||||
|
def long_syntax():
|
||||||
|
assert type(port_data) is dict
|
||||||
|
assert port_data["target"]
|
||||||
|
|
||||||
|
container_port: str = str(port_data["target"])
|
||||||
|
host_port: str = ""
|
||||||
|
protocol: Protocol = Protocol.any
|
||||||
|
|
||||||
|
if port_data.get("published"):
|
||||||
|
host_port = str(port_data["published"])
|
||||||
|
else:
|
||||||
|
host_port = container_port
|
||||||
|
|
||||||
|
if port_data.get("host_ip"):
|
||||||
|
host_ip = str(port_data["host_ip"])
|
||||||
|
host_port = f"{host_ip}:{host_port}"
|
||||||
|
else:
|
||||||
|
host_port = f"0.0.0.0:{host_port}"
|
||||||
|
|
||||||
|
if port_data.get("protocol"):
|
||||||
|
protocol = Protocol[str(port_data["protocol"])]
|
||||||
|
|
||||||
|
assert host_port, "Error parsing port, aborting."
|
||||||
|
|
||||||
|
service_ports.append(
|
||||||
|
Port(
|
||||||
|
host_port=host_port,
|
||||||
|
container_port=container_port,
|
||||||
|
protocol=protocol,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
long_syntax()
|
||||||
|
elif type(port_data) is str:
|
||||||
|
# ports that needs to parse using regex:
|
||||||
|
# - "3000"
|
||||||
|
# - "3000-3005"
|
||||||
|
# - "8000:8000"
|
||||||
|
# - "9090-9091:8080-8081"
|
||||||
|
# - "49100:22"
|
||||||
|
# - "127.0.0.1:8001:8001"
|
||||||
|
# - "127.0.0.1:5000-5010:5000-5010"
|
||||||
|
# - "6060:6060/udp"
|
||||||
|
|
||||||
|
def short_syntax():
|
||||||
|
assert type(port_data) is str
|
||||||
|
regex = r"(?P<host_ip>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:)?((?P<host_port>\d+(\-\d+)?):)?((?P<container_port>\d+(\-\d+)?))?(/(?P<protocol>\w+))?" # noqa: E501
|
||||||
|
match = re.match(regex, port_data)
|
||||||
|
if match:
|
||||||
|
host_ip: Optional[str] = match.group("host_ip")
|
||||||
|
host_port: Optional[str] = match.group("host_port")
|
||||||
|
container_port: Optional[str] = match.group("container_port")
|
||||||
|
protocol: Optional[str] = match.group("protocol")
|
||||||
|
|
||||||
|
assert container_port, "Invalid port format, aborting."
|
||||||
|
|
||||||
|
if container_port and not host_port:
|
||||||
|
host_port = container_port
|
||||||
|
|
||||||
|
if host_ip:
|
||||||
|
host_port = f"{host_ip}{host_port}"
|
||||||
|
else:
|
||||||
|
host_port = f"0.0.0.0:{host_port}"
|
||||||
|
|
||||||
|
assert host_port, "Error while parsing port, aborting."
|
||||||
|
|
||||||
|
if protocol:
|
||||||
|
service_ports.append(
|
||||||
|
Port(
|
||||||
|
host_port=host_port,
|
||||||
|
container_port=container_port,
|
||||||
|
protocol=Protocol[protocol],
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
service_ports.append(
|
||||||
|
Port(
|
||||||
|
host_port=host_port,
|
||||||
|
container_port=container_port,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
short_syntax()
|
||||||
|
|
||||||
|
service_depends_on: List[str] = []
|
||||||
|
if service.get("depends_on"):
|
||||||
|
if type(service["depends_on"]) is list:
|
||||||
|
for depends_on in service["depends_on"]:
|
||||||
|
service_depends_on.append(str(depends_on))
|
||||||
|
elif type(service["depends_on"]) is dict:
|
||||||
|
service_depends_on = list(service["depends_on"].keys())
|
||||||
|
|
||||||
|
service_volumes: List[Volume] = []
|
||||||
|
if service.get("volumes"):
|
||||||
|
assert type(service["volumes"]) is list
|
||||||
|
for volume_data in service["volumes"]:
|
||||||
|
if type(volume_data) is dict:
|
||||||
|
assert volume_data["source"] and volume_data["target"], "Invalid volume input, aborting."
|
||||||
|
|
||||||
|
volume_source: str = str(volume_data["source"])
|
||||||
|
volume_target: str = str(volume_data["target"])
|
||||||
|
volume_type: VolumeType = VolumeType.volume
|
||||||
|
|
||||||
|
if volume_data.get("type"):
|
||||||
|
volume_type = VolumeType[str(volume_data["type"])]
|
||||||
|
|
||||||
|
service_volumes.append(Volume(source=volume_source, target=volume_target, type=volume_type))
|
||||||
|
elif type(volume_data) is str:
|
||||||
|
assert ":" in volume_data, "Invalid volume input, aborting."
|
||||||
|
|
||||||
|
spilt_data = volume_data.split(":")
|
||||||
|
if len(spilt_data) == 2:
|
||||||
|
service_volumes.append(Volume(source=spilt_data[0], target=spilt_data[1]))
|
||||||
|
elif len(spilt_data) == 3:
|
||||||
|
service_volumes.append(
|
||||||
|
Volume(source=spilt_data[0], target=spilt_data[1], access_mode=spilt_data[2])
|
||||||
|
)
|
||||||
|
|
||||||
|
service_links: List[str] = []
|
||||||
|
if service.get("links"):
|
||||||
|
service_links = service["links"]
|
||||||
|
|
||||||
|
services.append(
|
||||||
|
Service(
|
||||||
|
name=service_name,
|
||||||
|
image=service_image,
|
||||||
|
networks=service_networks,
|
||||||
|
extends=service_extends,
|
||||||
|
ports=service_ports,
|
||||||
|
depends_on=service_depends_on,
|
||||||
|
volumes=service_volumes,
|
||||||
|
links=service_links,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
# Service print debug
|
||||||
|
# print("--------------------")
|
||||||
|
# print("Service name: {}".format(service_name))
|
||||||
|
# print("image: {}".format(service_image))
|
||||||
|
# print("networks: {}".format(service_networks))
|
||||||
|
# print("image: {}".format(service_image))
|
||||||
|
# print("extends: {}".format(service_extends))
|
||||||
|
# print("ports: {}".format(service_ports))
|
||||||
|
# print("depends: {}".format(service_depends_on))
|
||||||
|
|
||||||
|
return services
|
||||||
|
|
26
compose_viz/port.py
Normal file
26
compose_viz/port.py
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
from enum import Enum
|
||||||
|
|
||||||
|
|
||||||
|
class Protocol(str, Enum):
|
||||||
|
tcp = "tcp"
|
||||||
|
udp = "udp"
|
||||||
|
any = "any"
|
||||||
|
|
||||||
|
|
||||||
|
class Port:
|
||||||
|
def __init__(self, host_port: str, container_port: str, protocol: Protocol = Protocol.any):
|
||||||
|
self._host_port = host_port
|
||||||
|
self._container_port = container_port
|
||||||
|
self._protocol = protocol
|
||||||
|
|
||||||
|
@property
|
||||||
|
def host_port(self):
|
||||||
|
return self._host_port
|
||||||
|
|
||||||
|
@property
|
||||||
|
def container_port(self):
|
||||||
|
return self._container_port
|
||||||
|
|
||||||
|
@property
|
||||||
|
def protocol(self):
|
||||||
|
return self._protocol
|
|
@ -1,13 +1,59 @@
|
||||||
from typing import List
|
from typing import List, Optional
|
||||||
|
|
||||||
|
from compose_viz.extends import Extends
|
||||||
|
from compose_viz.port import Port
|
||||||
|
from compose_viz.volume import Volume
|
||||||
|
|
||||||
|
|
||||||
class Service:
|
class Service:
|
||||||
def __init__(self, name: str, image: str, ports: List[str] = [], networks: List[str] = [], volumes: List[str] = [], depends_on: List[str] = [], links: List[str] = [], extends: List[str] = []) -> None:
|
def __init__(
|
||||||
self.name = name
|
self,
|
||||||
self.image = image
|
name: str,
|
||||||
self.ports = ports
|
image: Optional[str] = None,
|
||||||
self.networks = networks
|
ports: List[Port] = [],
|
||||||
self.volumes = volumes
|
networks: List[str] = [],
|
||||||
self.depends_on = depends_on
|
volumes: List[Volume] = [],
|
||||||
self.links = links
|
depends_on: List[str] = [],
|
||||||
self.extends = extends
|
links: List[str] = [],
|
||||||
|
extends: Optional[Extends] = None,
|
||||||
|
) -> None:
|
||||||
|
self._name = name
|
||||||
|
self._image = image
|
||||||
|
self._ports = ports
|
||||||
|
self._networks = networks
|
||||||
|
self._volumes = volumes
|
||||||
|
self._depends_on = depends_on
|
||||||
|
self._links = links
|
||||||
|
self._extends = extends
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self):
|
||||||
|
return self._name
|
||||||
|
|
||||||
|
@property
|
||||||
|
def image(self):
|
||||||
|
return self._image
|
||||||
|
|
||||||
|
@property
|
||||||
|
def ports(self):
|
||||||
|
return self._ports
|
||||||
|
|
||||||
|
@property
|
||||||
|
def networks(self):
|
||||||
|
return self._networks
|
||||||
|
|
||||||
|
@property
|
||||||
|
def volumes(self):
|
||||||
|
return self._volumes
|
||||||
|
|
||||||
|
@property
|
||||||
|
def depends_on(self):
|
||||||
|
return self._depends_on
|
||||||
|
|
||||||
|
@property
|
||||||
|
def links(self):
|
||||||
|
return self._links
|
||||||
|
|
||||||
|
@property
|
||||||
|
def extends(self):
|
||||||
|
return self._extends
|
||||||
|
|
32
compose_viz/volume.py
Normal file
32
compose_viz/volume.py
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
from enum import Enum
|
||||||
|
|
||||||
|
|
||||||
|
class VolumeType(str, Enum):
|
||||||
|
volume = "volume"
|
||||||
|
bind = "bind"
|
||||||
|
tmpfs = "tmpfs"
|
||||||
|
npipe = "npipe"
|
||||||
|
|
||||||
|
|
||||||
|
class Volume:
|
||||||
|
def __init__(self, source: str, target: str, type: VolumeType = VolumeType.volume, access_mode: str = "rw"):
|
||||||
|
self._source = source
|
||||||
|
self._target = target
|
||||||
|
self._type = type
|
||||||
|
self._access_mode = access_mode
|
||||||
|
|
||||||
|
@property
|
||||||
|
def source(self):
|
||||||
|
return self._source
|
||||||
|
|
||||||
|
@property
|
||||||
|
def target(self):
|
||||||
|
return self._target
|
||||||
|
|
||||||
|
@property
|
||||||
|
def type(self):
|
||||||
|
return self._type
|
||||||
|
|
||||||
|
@property
|
||||||
|
def access_mode(self):
|
||||||
|
return self._access_mode
|
BIN
examples/full-stack-node-app/compose-viz.png
Normal file
BIN
examples/full-stack-node-app/compose-viz.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 92 KiB |
87
examples/full-stack-node-app/docker-compose.yml
Normal file
87
examples/full-stack-node-app/docker-compose.yml
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
version: "3.9"
|
||||||
|
|
||||||
|
services:
|
||||||
|
node:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile.node
|
||||||
|
|
||||||
|
api:
|
||||||
|
image: "awesome/api"
|
||||||
|
extends:
|
||||||
|
service: node
|
||||||
|
build:
|
||||||
|
args:
|
||||||
|
PACKAGE_PATH: api
|
||||||
|
WORKING_DIR: /usr/src/
|
||||||
|
expose:
|
||||||
|
- 8000
|
||||||
|
ports:
|
||||||
|
- 8000:8000
|
||||||
|
environment:
|
||||||
|
- NODE_ENV=development
|
||||||
|
volumes:
|
||||||
|
- ./api:/usr/src
|
||||||
|
depends_on:
|
||||||
|
- db
|
||||||
|
- adminer
|
||||||
|
- redis
|
||||||
|
networks:
|
||||||
|
- front-tier
|
||||||
|
- back-tier
|
||||||
|
command: ["npm", "start"]
|
||||||
|
|
||||||
|
frontend:
|
||||||
|
extends:
|
||||||
|
service: node
|
||||||
|
build:
|
||||||
|
args:
|
||||||
|
PACKAGE_PATH: frontend
|
||||||
|
WORKING_DIR: /usr/src/
|
||||||
|
expose:
|
||||||
|
- 3000
|
||||||
|
ports:
|
||||||
|
- 3000:3000
|
||||||
|
volumes:
|
||||||
|
- ./frontend:/usr/src
|
||||||
|
depends_on:
|
||||||
|
- api
|
||||||
|
networks:
|
||||||
|
- front-tier
|
||||||
|
command: ["npm", "start"]
|
||||||
|
|
||||||
|
db:
|
||||||
|
image: "awesome/db"
|
||||||
|
extends:
|
||||||
|
service: postgres
|
||||||
|
file: postgres.yml
|
||||||
|
restart: always
|
||||||
|
networks:
|
||||||
|
- back-tier
|
||||||
|
volumes:
|
||||||
|
- "db-data:/data"
|
||||||
|
- type: bind
|
||||||
|
source: /var/run/postgres/postgres.sock
|
||||||
|
target: /var/run/postgres/postgres.sock
|
||||||
|
|
||||||
|
redis:
|
||||||
|
image: "awesome/redis"
|
||||||
|
restart: always
|
||||||
|
networks:
|
||||||
|
- back-tier
|
||||||
|
expose:
|
||||||
|
- 6379
|
||||||
|
|
||||||
|
adminer:
|
||||||
|
image: "awesome/adminer"
|
||||||
|
networks:
|
||||||
|
- back-tier
|
||||||
|
ports:
|
||||||
|
- 8080:8080
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
db-data:
|
||||||
|
|
||||||
|
networks:
|
||||||
|
front-tier:
|
||||||
|
back-tier:
|
5
examples/full-stack-node-app/postgres.yml
Normal file
5
examples/full-stack-node-app/postgres.yml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
version: "3.9"
|
||||||
|
|
||||||
|
services:
|
||||||
|
postgres:
|
||||||
|
image: awesome/postgres
|
BIN
examples/non-normative/compose-viz.png
Normal file
BIN
examples/non-normative/compose-viz.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 48 KiB |
|
@ -9,10 +9,9 @@ services:
|
||||||
image: awesome/monitoring
|
image: awesome/monitoring
|
||||||
networks:
|
networks:
|
||||||
- admin
|
- admin
|
||||||
|
|
||||||
|
|
||||||
backend:
|
backend:
|
||||||
image: awesome/backend
|
|
||||||
networks:
|
networks:
|
||||||
back-tier:
|
back-tier:
|
||||||
aliases:
|
aliases:
|
BIN
examples/voting-app/compose-viz.png
Normal file
BIN
examples/voting-app/compose-viz.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 68 KiB |
89
examples/voting-app/docker-compose.yml
Normal file
89
examples/voting-app/docker-compose.yml
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
# https://github.com/docker/labs/blob/master/beginner/chapters/votingapp.md
|
||||||
|
|
||||||
|
version: "3.9"
|
||||||
|
|
||||||
|
services:
|
||||||
|
redis:
|
||||||
|
image: redis:alpine
|
||||||
|
ports:
|
||||||
|
- "6379"
|
||||||
|
networks:
|
||||||
|
- frontend
|
||||||
|
deploy:
|
||||||
|
replicas: 2
|
||||||
|
update_config:
|
||||||
|
parallelism: 2
|
||||||
|
delay: 10s
|
||||||
|
restart_policy:
|
||||||
|
condition: on-failure
|
||||||
|
db:
|
||||||
|
image: postgres:9.4
|
||||||
|
volumes:
|
||||||
|
- db-data:/var/lib/postgresql/data
|
||||||
|
networks:
|
||||||
|
- backend
|
||||||
|
deploy:
|
||||||
|
placement:
|
||||||
|
constraints: [node.role == manager]
|
||||||
|
vote:
|
||||||
|
image: dockersamples/examplevotingapp_vote:before
|
||||||
|
ports:
|
||||||
|
- 5000:80
|
||||||
|
networks:
|
||||||
|
- frontend
|
||||||
|
depends_on:
|
||||||
|
- redis
|
||||||
|
deploy:
|
||||||
|
replicas: 2
|
||||||
|
update_config:
|
||||||
|
parallelism: 2
|
||||||
|
restart_policy:
|
||||||
|
condition: on-failure
|
||||||
|
result:
|
||||||
|
image: dockersamples/examplevotingapp_result:before
|
||||||
|
ports:
|
||||||
|
- 5001:80
|
||||||
|
networks:
|
||||||
|
- backend
|
||||||
|
depends_on:
|
||||||
|
- db
|
||||||
|
deploy:
|
||||||
|
replicas: 1
|
||||||
|
update_config:
|
||||||
|
parallelism: 2
|
||||||
|
delay: 10s
|
||||||
|
restart_policy:
|
||||||
|
condition: on-failure
|
||||||
|
worker:
|
||||||
|
image: dockersamples/examplevotingapp_worker
|
||||||
|
networks:
|
||||||
|
- frontend
|
||||||
|
- backend
|
||||||
|
deploy:
|
||||||
|
mode: replicated
|
||||||
|
replicas: 1
|
||||||
|
labels: [APP=VOTING]
|
||||||
|
restart_policy:
|
||||||
|
condition: on-failure
|
||||||
|
delay: 10s
|
||||||
|
max_attempts: 3
|
||||||
|
window: 120s
|
||||||
|
placement:
|
||||||
|
constraints: [node.role == manager]
|
||||||
|
visualizer:
|
||||||
|
image: dockersamples/visualizer
|
||||||
|
ports:
|
||||||
|
- "8080:8080"
|
||||||
|
stop_grace_period: 1m30s
|
||||||
|
volumes:
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
deploy:
|
||||||
|
placement:
|
||||||
|
constraints: [node.role == manager]
|
||||||
|
|
||||||
|
networks:
|
||||||
|
frontend:
|
||||||
|
backend:
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
db-data:
|
341
poetry.lock
generated
341
poetry.lock
generated
|
@ -20,6 +20,14 @@ docs = ["furo", "sphinx", "zope.interface", "sphinx-notfound-page"]
|
||||||
tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "cloudpickle"]
|
tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "cloudpickle"]
|
||||||
tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "cloudpickle"]
|
tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "cloudpickle"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfgv"
|
||||||
|
version = "3.3.1"
|
||||||
|
description = "Validate configuration and produce human readable error messages."
|
||||||
|
category = "dev"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.6.1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "click"
|
name = "click"
|
||||||
version = "8.1.3"
|
version = "8.1.3"
|
||||||
|
@ -39,6 +47,64 @@ category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "coverage"
|
||||||
|
version = "6.3.3"
|
||||||
|
description = "Code coverage measurement for Python"
|
||||||
|
category = "dev"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.7"
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
tomli = {version = "*", optional = true, markers = "extra == \"toml\""}
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
toml = ["tomli"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "distlib"
|
||||||
|
version = "0.3.4"
|
||||||
|
description = "Distribution utilities"
|
||||||
|
category = "dev"
|
||||||
|
optional = false
|
||||||
|
python-versions = "*"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "filelock"
|
||||||
|
version = "3.7.0"
|
||||||
|
description = "A platform independent file lock."
|
||||||
|
category = "dev"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.7"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
docs = ["furo (>=2021.8.17b43)", "sphinx (>=4.1)", "sphinx-autodoc-typehints (>=1.12)"]
|
||||||
|
testing = ["covdefaults (>=1.2.0)", "coverage (>=4)", "pytest (>=4)", "pytest-cov", "pytest-timeout (>=1.4.2)"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "graphviz"
|
||||||
|
version = "0.20"
|
||||||
|
description = "Simple Python interface for Graphviz"
|
||||||
|
category = "main"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.7"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
dev = ["tox (>=3)", "flake8", "pep8-naming", "wheel", "twine"]
|
||||||
|
docs = ["sphinx (>=4)", "sphinx-autodoc-typehints", "sphinx-rtd-theme"]
|
||||||
|
test = ["pytest (>=7)", "pytest-mock (>=3)", "mock (>=4)", "pytest-cov", "coverage"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "identify"
|
||||||
|
version = "2.5.0"
|
||||||
|
description = "File identification library for Python"
|
||||||
|
category = "dev"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.7"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
license = ["ukkonen"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "iniconfig"
|
name = "iniconfig"
|
||||||
version = "1.1.1"
|
version = "1.1.1"
|
||||||
|
@ -47,6 +113,14 @@ category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = "*"
|
python-versions = "*"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nodeenv"
|
||||||
|
version = "1.6.0"
|
||||||
|
description = "Node.js virtual environment builder"
|
||||||
|
category = "dev"
|
||||||
|
optional = false
|
||||||
|
python-versions = "*"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "packaging"
|
name = "packaging"
|
||||||
version = "21.3"
|
version = "21.3"
|
||||||
|
@ -58,6 +132,18 @@ python-versions = ">=3.6"
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
pyparsing = ">=2.0.2,<3.0.5 || >3.0.5"
|
pyparsing = ">=2.0.2,<3.0.5 || >3.0.5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "platformdirs"
|
||||||
|
version = "2.5.2"
|
||||||
|
description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
|
||||||
|
category = "dev"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.7"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
docs = ["furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)", "sphinx (>=4)"]
|
||||||
|
test = ["appdirs (==1.4.4)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)", "pytest (>=6)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pluggy"
|
name = "pluggy"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
|
@ -70,6 +156,22 @@ python-versions = ">=3.6"
|
||||||
dev = ["pre-commit", "tox"]
|
dev = ["pre-commit", "tox"]
|
||||||
testing = ["pytest", "pytest-benchmark"]
|
testing = ["pytest", "pytest-benchmark"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pre-commit"
|
||||||
|
version = "2.19.0"
|
||||||
|
description = "A framework for managing and maintaining multi-language pre-commit hooks."
|
||||||
|
category = "dev"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.7"
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
cfgv = ">=2.0.0"
|
||||||
|
identify = ">=1.0.0"
|
||||||
|
nodeenv = ">=0.11.1"
|
||||||
|
pyyaml = ">=5.1"
|
||||||
|
toml = "*"
|
||||||
|
virtualenv = ">=20.0.8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "py"
|
name = "py"
|
||||||
version = "1.11.0"
|
version = "1.11.0"
|
||||||
|
@ -110,6 +212,68 @@ tomli = ">=1.0.0"
|
||||||
[package.extras]
|
[package.extras]
|
||||||
testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"]
|
testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pytest-cov"
|
||||||
|
version = "3.0.0"
|
||||||
|
description = "Pytest plugin for measuring coverage."
|
||||||
|
category = "dev"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.6"
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
coverage = {version = ">=5.2.1", extras = ["toml"]}
|
||||||
|
pytest = ">=4.6"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
testing = ["fields", "hunter", "process-tests", "six", "pytest-xdist", "virtualenv"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pyyaml"
|
||||||
|
version = "6.0"
|
||||||
|
description = "YAML parser and emitter for Python"
|
||||||
|
category = "main"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ruamel.yaml"
|
||||||
|
version = "0.17.21"
|
||||||
|
description = "ruamel.yaml is a YAML parser/emitter that supports roundtrip preservation of comments, seq/map flow style, and map key order"
|
||||||
|
category = "main"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3"
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
"ruamel.yaml.clib" = {version = ">=0.2.6", markers = "platform_python_implementation == \"CPython\" and python_version < \"3.11\""}
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
docs = ["ryd"]
|
||||||
|
jinja2 = ["ruamel.yaml.jinja2 (>=0.2)"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ruamel.yaml.clib"
|
||||||
|
version = "0.2.6"
|
||||||
|
description = "C version of reader, parser and emitter for ruamel.yaml derived from libyaml"
|
||||||
|
category = "main"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "six"
|
||||||
|
version = "1.16.0"
|
||||||
|
description = "Python 2 and 3 compatibility utilities"
|
||||||
|
category = "dev"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml"
|
||||||
|
version = "0.10.2"
|
||||||
|
description = "Python Library for Tom's Obvious, Minimal Language"
|
||||||
|
category = "dev"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tomli"
|
name = "tomli"
|
||||||
version = "2.0.1"
|
version = "2.0.1"
|
||||||
|
@ -135,10 +299,28 @@ dev = ["autoflake (>=1.3.1,<2.0.0)", "flake8 (>=3.8.3,<4.0.0)"]
|
||||||
doc = ["mkdocs (>=1.1.2,<2.0.0)", "mkdocs-material (>=8.1.4,<9.0.0)", "mdx-include (>=1.4.1,<2.0.0)"]
|
doc = ["mkdocs (>=1.1.2,<2.0.0)", "mkdocs-material (>=8.1.4,<9.0.0)", "mdx-include (>=1.4.1,<2.0.0)"]
|
||||||
test = ["shellingham (>=1.3.0,<2.0.0)", "pytest (>=4.4.0,<5.4.0)", "pytest-cov (>=2.10.0,<3.0.0)", "coverage (>=5.2,<6.0)", "pytest-xdist (>=1.32.0,<2.0.0)", "pytest-sugar (>=0.9.4,<0.10.0)", "mypy (==0.910)", "black (>=22.3.0,<23.0.0)", "isort (>=5.0.6,<6.0.0)"]
|
test = ["shellingham (>=1.3.0,<2.0.0)", "pytest (>=4.4.0,<5.4.0)", "pytest-cov (>=2.10.0,<3.0.0)", "coverage (>=5.2,<6.0)", "pytest-xdist (>=1.32.0,<2.0.0)", "pytest-sugar (>=0.9.4,<0.10.0)", "mypy (==0.910)", "black (>=22.3.0,<23.0.0)", "isort (>=5.0.6,<6.0.0)"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "virtualenv"
|
||||||
|
version = "20.14.1"
|
||||||
|
description = "Virtual Python Environment builder"
|
||||||
|
category = "dev"
|
||||||
|
optional = false
|
||||||
|
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
distlib = ">=0.3.1,<1"
|
||||||
|
filelock = ">=3.2,<4"
|
||||||
|
platformdirs = ">=2,<3"
|
||||||
|
six = ">=1.9.0,<2"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
docs = ["proselint (>=0.10.2)", "sphinx (>=3)", "sphinx-argparse (>=0.2.5)", "sphinx-rtd-theme (>=0.4.3)", "towncrier (>=21.3)"]
|
||||||
|
testing = ["coverage (>=4)", "coverage-enable-subprocess (>=1)", "flaky (>=3)", "pytest (>=4)", "pytest-env (>=0.6.2)", "pytest-freezegun (>=0.4.1)", "pytest-mock (>=2)", "pytest-randomly (>=1)", "pytest-timeout (>=1)", "packaging (>=20.0)"]
|
||||||
|
|
||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "1.1"
|
lock-version = "1.1"
|
||||||
python-versions = "^3.9"
|
python-versions = "^3.9"
|
||||||
content-hash = "a80ea7abd86b8e5579a192dfa02a55d2219a3a1850bad12da89c30aa42e99156"
|
content-hash = "e1b68a4c83f398e841e6f38823ea18f3cb27b0b251689d0398ae39c03ddc4a47"
|
||||||
|
|
||||||
[metadata.files]
|
[metadata.files]
|
||||||
atomicwrites = [
|
atomicwrites = [
|
||||||
|
@ -149,6 +331,10 @@ attrs = [
|
||||||
{file = "attrs-21.4.0-py2.py3-none-any.whl", hash = "sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4"},
|
{file = "attrs-21.4.0-py2.py3-none-any.whl", hash = "sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4"},
|
||||||
{file = "attrs-21.4.0.tar.gz", hash = "sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd"},
|
{file = "attrs-21.4.0.tar.gz", hash = "sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd"},
|
||||||
]
|
]
|
||||||
|
cfgv = [
|
||||||
|
{file = "cfgv-3.3.1-py2.py3-none-any.whl", hash = "sha256:c6a0883f3917a037485059700b9e75da2464e6c27051014ad85ba6aaa5884426"},
|
||||||
|
{file = "cfgv-3.3.1.tar.gz", hash = "sha256:f5a830efb9ce7a445376bb66ec94c638a9787422f96264c98edc6bdeed8ab736"},
|
||||||
|
]
|
||||||
click = [
|
click = [
|
||||||
{file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"},
|
{file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"},
|
||||||
{file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"},
|
{file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"},
|
||||||
|
@ -157,18 +343,89 @@ colorama = [
|
||||||
{file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"},
|
{file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"},
|
||||||
{file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"},
|
{file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"},
|
||||||
]
|
]
|
||||||
|
coverage = [
|
||||||
|
{file = "coverage-6.3.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df32ee0f4935a101e4b9a5f07b617d884a531ed5666671ff6ac66d2e8e8246d8"},
|
||||||
|
{file = "coverage-6.3.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:75b5dbffc334e0beb4f6c503fb95e6d422770fd2d1b40a64898ea26d6c02742d"},
|
||||||
|
{file = "coverage-6.3.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:114944e6061b68a801c5da5427b9173a0dd9d32cd5fcc18a13de90352843737d"},
|
||||||
|
{file = "coverage-6.3.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2ab88a01cd180b5640ccc9c47232e31924d5f9967ab7edd7e5c91c68eee47a69"},
|
||||||
|
{file = "coverage-6.3.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad8f9068f5972a46d50fe5f32c09d6ee11da69c560fcb1b4c3baea246ca4109b"},
|
||||||
|
{file = "coverage-6.3.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4cd696aa712e6cd16898d63cf66139dc70d998f8121ab558f0e1936396dbc579"},
|
||||||
|
{file = "coverage-6.3.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:c1a9942e282cc9d3ed522cd3e3cab081149b27ea3bda72d6f61f84eaf88c1a63"},
|
||||||
|
{file = "coverage-6.3.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c06455121a089252b5943ea682187a4e0a5cf0a3fb980eb8e7ce394b144430a9"},
|
||||||
|
{file = "coverage-6.3.3-cp310-cp310-win32.whl", hash = "sha256:cb5311d6ccbd22578c80028c5e292a7ab9adb91bd62c1982087fad75abe2e63d"},
|
||||||
|
{file = "coverage-6.3.3-cp310-cp310-win_amd64.whl", hash = "sha256:6d4a6f30f611e657495cc81a07ff7aa8cd949144e7667c5d3e680d73ba7a70e4"},
|
||||||
|
{file = "coverage-6.3.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:79bf405432428e989cad7b8bc60581963238f7645ae8a404f5dce90236cc0293"},
|
||||||
|
{file = "coverage-6.3.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:338c417613f15596af9eb7a39353b60abec9d8ce1080aedba5ecee6a5d85f8d3"},
|
||||||
|
{file = "coverage-6.3.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:db094a6a4ae6329ed322a8973f83630b12715654c197dd392410400a5bfa1a73"},
|
||||||
|
{file = "coverage-6.3.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1414e8b124611bf4df8d77215bd32cba6e3425da8ce9c1f1046149615e3a9a31"},
|
||||||
|
{file = "coverage-6.3.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:93b16b08f94c92cab88073ffd185070cdcb29f1b98df8b28e6649145b7f2c90d"},
|
||||||
|
{file = "coverage-6.3.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:fbc86ae8cc129c801e7baaafe3addf3c8d49c9c1597c44bdf2d78139707c3c62"},
|
||||||
|
{file = "coverage-6.3.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:b5ba058610e8289a07db2a57bce45a1793ec0d3d11db28c047aae2aa1a832572"},
|
||||||
|
{file = "coverage-6.3.3-cp37-cp37m-win32.whl", hash = "sha256:8329635c0781927a2c6ae068461e19674c564e05b86736ab8eb29c420ee7dc20"},
|
||||||
|
{file = "coverage-6.3.3-cp37-cp37m-win_amd64.whl", hash = "sha256:e5af1feee71099ae2e3b086ec04f57f9950e1be9ecf6c420696fea7977b84738"},
|
||||||
|
{file = "coverage-6.3.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e814a4a5a1d95223b08cdb0f4f57029e8eab22ffdbae2f97107aeef28554517e"},
|
||||||
|
{file = "coverage-6.3.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:61f4fbf3633cb0713437291b8848634ea97f89c7e849c2be17a665611e433f53"},
|
||||||
|
{file = "coverage-6.3.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3401b0d2ed9f726fadbfa35102e00d1b3547b73772a1de5508ef3bdbcb36afe7"},
|
||||||
|
{file = "coverage-6.3.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8586b177b4407f988731eb7f41967415b2197f35e2a6ee1a9b9b561f6323c8e9"},
|
||||||
|
{file = "coverage-6.3.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:892e7fe32191960da559a14536768a62e83e87bbb867e1b9c643e7e0fbce2579"},
|
||||||
|
{file = "coverage-6.3.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:afb03f981fadb5aed1ac6e3dd34f0488e1a0875623d557b6fad09b97a942b38a"},
|
||||||
|
{file = "coverage-6.3.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:cbe91bc84be4e5ef0b1480d15c7b18e29c73bdfa33e07d3725da7d18e1b0aff2"},
|
||||||
|
{file = "coverage-6.3.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:91502bf27cbd5c83c95cfea291ef387469f2387508645602e1ca0fd8a4ba7548"},
|
||||||
|
{file = "coverage-6.3.3-cp38-cp38-win32.whl", hash = "sha256:c488db059848702aff30aa1d90ef87928d4e72e4f00717343800546fdbff0a94"},
|
||||||
|
{file = "coverage-6.3.3-cp38-cp38-win_amd64.whl", hash = "sha256:ceb6534fcdfb5c503affb6b1130db7b5bfc8a0f77fa34880146f7a5c117987d0"},
|
||||||
|
{file = "coverage-6.3.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:cc692c9ee18f0dd3214843779ba6b275ee4bb9b9a5745ba64265bce911aefd1a"},
|
||||||
|
{file = "coverage-6.3.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:462105283de203df8de58a68c1bb4ba2a8a164097c2379f664fa81d6baf94b81"},
|
||||||
|
{file = "coverage-6.3.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc972d829ad5ef4d4c5fcabd2bbe2add84ce8236f64ba1c0c72185da3a273130"},
|
||||||
|
{file = "coverage-6.3.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:06f54765cdbce99901871d50fe9f41d58213f18e98b170a30ca34f47de7dd5e8"},
|
||||||
|
{file = "coverage-6.3.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7835f76a081787f0ca62a53504361b3869840a1620049b56d803a8cb3a9eeea3"},
|
||||||
|
{file = "coverage-6.3.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:6f5fee77ec3384b934797f1873758f796dfb4f167e1296dc00f8b2e023ce6ee9"},
|
||||||
|
{file = "coverage-6.3.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:baa8be8aba3dd1e976e68677be68a960a633a6d44c325757aefaa4d66175050f"},
|
||||||
|
{file = "coverage-6.3.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4d06380e777dd6b35ee936f333d55b53dc4a8271036ff884c909cf6e94be8b6c"},
|
||||||
|
{file = "coverage-6.3.3-cp39-cp39-win32.whl", hash = "sha256:f8cabc5fd0091976ab7b020f5708335033e422de25e20ddf9416bdce2b7e07d8"},
|
||||||
|
{file = "coverage-6.3.3-cp39-cp39-win_amd64.whl", hash = "sha256:9c9441d57b0963cf8340268ad62fc83de61f1613034b79c2b1053046af0c5284"},
|
||||||
|
{file = "coverage-6.3.3-pp36.pp37.pp38-none-any.whl", hash = "sha256:d522f1dc49127eab0bfbba4e90fa068ecff0899bbf61bf4065c790ddd6c177fe"},
|
||||||
|
{file = "coverage-6.3.3.tar.gz", hash = "sha256:2781c43bffbbec2b8867376d4d61916f5e9c4cc168232528562a61d1b4b01879"},
|
||||||
|
]
|
||||||
|
distlib = [
|
||||||
|
{file = "distlib-0.3.4-py2.py3-none-any.whl", hash = "sha256:6564fe0a8f51e734df6333d08b8b94d4ea8ee6b99b5ed50613f731fd4089f34b"},
|
||||||
|
{file = "distlib-0.3.4.zip", hash = "sha256:e4b58818180336dc9c529bfb9a0b58728ffc09ad92027a3f30b7cd91e3458579"},
|
||||||
|
]
|
||||||
|
filelock = [
|
||||||
|
{file = "filelock-3.7.0-py3-none-any.whl", hash = "sha256:c7b5fdb219b398a5b28c8e4c1893ef5f98ece6a38c6ab2c22e26ec161556fed6"},
|
||||||
|
{file = "filelock-3.7.0.tar.gz", hash = "sha256:b795f1b42a61bbf8ec7113c341dad679d772567b936fbd1bf43c9a238e673e20"},
|
||||||
|
]
|
||||||
|
graphviz = [
|
||||||
|
{file = "graphviz-0.20-py3-none-any.whl", hash = "sha256:62c5f48bcc534a45b4588c548ff75e419c1f1f3a33d31a91796ae80a7f581e4a"},
|
||||||
|
{file = "graphviz-0.20.zip", hash = "sha256:76bdfb73f42e72564ffe9c7299482f9d72f8e6cb8d54bce7b48ab323755e9ba5"},
|
||||||
|
]
|
||||||
|
identify = [
|
||||||
|
{file = "identify-2.5.0-py2.py3-none-any.whl", hash = "sha256:3acfe15a96e4272b4ec5662ee3e231ceba976ef63fd9980ed2ce9cc415df393f"},
|
||||||
|
{file = "identify-2.5.0.tar.gz", hash = "sha256:c83af514ea50bf2be2c4a3f2fb349442b59dc87284558ae9ff54191bff3541d2"},
|
||||||
|
]
|
||||||
iniconfig = [
|
iniconfig = [
|
||||||
{file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"},
|
{file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"},
|
||||||
{file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"},
|
{file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"},
|
||||||
]
|
]
|
||||||
|
nodeenv = [
|
||||||
|
{file = "nodeenv-1.6.0-py2.py3-none-any.whl", hash = "sha256:621e6b7076565ddcacd2db0294c0381e01fd28945ab36bcf00f41c5daf63bef7"},
|
||||||
|
{file = "nodeenv-1.6.0.tar.gz", hash = "sha256:3ef13ff90291ba2a4a7a4ff9a979b63ffdd00a464dbe04acf0ea6471517a4c2b"},
|
||||||
|
]
|
||||||
packaging = [
|
packaging = [
|
||||||
{file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"},
|
{file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"},
|
||||||
{file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"},
|
{file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"},
|
||||||
]
|
]
|
||||||
|
platformdirs = [
|
||||||
|
{file = "platformdirs-2.5.2-py3-none-any.whl", hash = "sha256:027d8e83a2d7de06bbac4e5ef7e023c02b863d7ea5d079477e722bb41ab25788"},
|
||||||
|
{file = "platformdirs-2.5.2.tar.gz", hash = "sha256:58c8abb07dcb441e6ee4b11d8df0ac856038f944ab98b7be6b27b2a3c7feef19"},
|
||||||
|
]
|
||||||
pluggy = [
|
pluggy = [
|
||||||
{file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"},
|
{file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"},
|
||||||
{file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"},
|
{file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"},
|
||||||
]
|
]
|
||||||
|
pre-commit = [
|
||||||
|
{file = "pre_commit-2.19.0-py2.py3-none-any.whl", hash = "sha256:10c62741aa5704faea2ad69cb550ca78082efe5697d6f04e5710c3c229afdd10"},
|
||||||
|
{file = "pre_commit-2.19.0.tar.gz", hash = "sha256:4233a1e38621c87d9dda9808c6606d7e7ba0e087cd56d3fe03202a01d2919615"},
|
||||||
|
]
|
||||||
py = [
|
py = [
|
||||||
{file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"},
|
{file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"},
|
||||||
{file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"},
|
{file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"},
|
||||||
|
@ -181,6 +438,84 @@ pytest = [
|
||||||
{file = "pytest-7.1.2-py3-none-any.whl", hash = "sha256:13d0e3ccfc2b6e26be000cb6568c832ba67ba32e719443bfe725814d3c42433c"},
|
{file = "pytest-7.1.2-py3-none-any.whl", hash = "sha256:13d0e3ccfc2b6e26be000cb6568c832ba67ba32e719443bfe725814d3c42433c"},
|
||||||
{file = "pytest-7.1.2.tar.gz", hash = "sha256:a06a0425453864a270bc45e71f783330a7428defb4230fb5e6a731fde06ecd45"},
|
{file = "pytest-7.1.2.tar.gz", hash = "sha256:a06a0425453864a270bc45e71f783330a7428defb4230fb5e6a731fde06ecd45"},
|
||||||
]
|
]
|
||||||
|
pytest-cov = [
|
||||||
|
{file = "pytest-cov-3.0.0.tar.gz", hash = "sha256:e7f0f5b1617d2210a2cabc266dfe2f4c75a8d32fb89eafb7ad9d06f6d076d470"},
|
||||||
|
{file = "pytest_cov-3.0.0-py3-none-any.whl", hash = "sha256:578d5d15ac4a25e5f961c938b85a05b09fdaae9deef3bb6de9a6e766622ca7a6"},
|
||||||
|
]
|
||||||
|
pyyaml = [
|
||||||
|
{file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"},
|
||||||
|
{file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"},
|
||||||
|
{file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc"},
|
||||||
|
{file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b"},
|
||||||
|
{file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"},
|
||||||
|
{file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"},
|
||||||
|
{file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"},
|
||||||
|
{file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"},
|
||||||
|
{file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"},
|
||||||
|
{file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"},
|
||||||
|
{file = "PyYAML-6.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4"},
|
||||||
|
{file = "PyYAML-6.0-cp36-cp36m-win32.whl", hash = "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293"},
|
||||||
|
{file = "PyYAML-6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57"},
|
||||||
|
{file = "PyYAML-6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c"},
|
||||||
|
{file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0"},
|
||||||
|
{file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4"},
|
||||||
|
{file = "PyYAML-6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9"},
|
||||||
|
{file = "PyYAML-6.0-cp37-cp37m-win32.whl", hash = "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737"},
|
||||||
|
{file = "PyYAML-6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d"},
|
||||||
|
{file = "PyYAML-6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b"},
|
||||||
|
{file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba"},
|
||||||
|
{file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34"},
|
||||||
|
{file = "PyYAML-6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287"},
|
||||||
|
{file = "PyYAML-6.0-cp38-cp38-win32.whl", hash = "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78"},
|
||||||
|
{file = "PyYAML-6.0-cp38-cp38-win_amd64.whl", hash = "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07"},
|
||||||
|
{file = "PyYAML-6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b"},
|
||||||
|
{file = "PyYAML-6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174"},
|
||||||
|
{file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803"},
|
||||||
|
{file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3"},
|
||||||
|
{file = "PyYAML-6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0"},
|
||||||
|
{file = "PyYAML-6.0-cp39-cp39-win32.whl", hash = "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb"},
|
||||||
|
{file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"},
|
||||||
|
{file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"},
|
||||||
|
]
|
||||||
|
"ruamel.yaml" = [
|
||||||
|
{file = "ruamel.yaml-0.17.21-py3-none-any.whl", hash = "sha256:742b35d3d665023981bd6d16b3d24248ce5df75fdb4e2924e93a05c1f8b61ca7"},
|
||||||
|
{file = "ruamel.yaml-0.17.21.tar.gz", hash = "sha256:8b7ce697a2f212752a35c1ac414471dc16c424c9573be4926b56ff3f5d23b7af"},
|
||||||
|
]
|
||||||
|
"ruamel.yaml.clib" = [
|
||||||
|
{file = "ruamel.yaml.clib-0.2.6-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:6e7be2c5bcb297f5b82fee9c665eb2eb7001d1050deaba8471842979293a80b0"},
|
||||||
|
{file = "ruamel.yaml.clib-0.2.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:221eca6f35076c6ae472a531afa1c223b9c29377e62936f61bc8e6e8bdc5f9e7"},
|
||||||
|
{file = "ruamel.yaml.clib-0.2.6-cp310-cp310-win32.whl", hash = "sha256:1070ba9dd7f9370d0513d649420c3b362ac2d687fe78c6e888f5b12bf8bc7bee"},
|
||||||
|
{file = "ruamel.yaml.clib-0.2.6-cp310-cp310-win_amd64.whl", hash = "sha256:77df077d32921ad46f34816a9a16e6356d8100374579bc35e15bab5d4e9377de"},
|
||||||
|
{file = "ruamel.yaml.clib-0.2.6-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:cfdb9389d888c5b74af297e51ce357b800dd844898af9d4a547ffc143fa56751"},
|
||||||
|
{file = "ruamel.yaml.clib-0.2.6-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:7b2927e92feb51d830f531de4ccb11b320255ee95e791022555971c466af4527"},
|
||||||
|
{file = "ruamel.yaml.clib-0.2.6-cp35-cp35m-win32.whl", hash = "sha256:ada3f400d9923a190ea8b59c8f60680c4ef8a4b0dfae134d2f2ff68429adfab5"},
|
||||||
|
{file = "ruamel.yaml.clib-0.2.6-cp35-cp35m-win_amd64.whl", hash = "sha256:de9c6b8a1ba52919ae919f3ae96abb72b994dd0350226e28f3686cb4f142165c"},
|
||||||
|
{file = "ruamel.yaml.clib-0.2.6-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:d67f273097c368265a7b81e152e07fb90ed395df6e552b9fa858c6d2c9f42502"},
|
||||||
|
{file = "ruamel.yaml.clib-0.2.6-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:72a2b8b2ff0a627496aad76f37a652bcef400fd861721744201ef1b45199ab78"},
|
||||||
|
{file = "ruamel.yaml.clib-0.2.6-cp36-cp36m-win32.whl", hash = "sha256:9efef4aab5353387b07f6b22ace0867032b900d8e91674b5d8ea9150db5cae94"},
|
||||||
|
{file = "ruamel.yaml.clib-0.2.6-cp36-cp36m-win_amd64.whl", hash = "sha256:846fc8336443106fe23f9b6d6b8c14a53d38cef9a375149d61f99d78782ea468"},
|
||||||
|
{file = "ruamel.yaml.clib-0.2.6-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0847201b767447fc33b9c235780d3aa90357d20dd6108b92be544427bea197dd"},
|
||||||
|
{file = "ruamel.yaml.clib-0.2.6-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:78988ed190206672da0f5d50c61afef8f67daa718d614377dcd5e3ed85ab4a99"},
|
||||||
|
{file = "ruamel.yaml.clib-0.2.6-cp37-cp37m-win32.whl", hash = "sha256:a49e0161897901d1ac9c4a79984b8410f450565bbad64dbfcbf76152743a0cdb"},
|
||||||
|
{file = "ruamel.yaml.clib-0.2.6-cp37-cp37m-win_amd64.whl", hash = "sha256:bf75d28fa071645c529b5474a550a44686821decebdd00e21127ef1fd566eabe"},
|
||||||
|
{file = "ruamel.yaml.clib-0.2.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a32f8d81ea0c6173ab1b3da956869114cae53ba1e9f72374032e33ba3118c233"},
|
||||||
|
{file = "ruamel.yaml.clib-0.2.6-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7f7ecb53ae6848f959db6ae93bdff1740e651809780822270eab111500842a84"},
|
||||||
|
{file = "ruamel.yaml.clib-0.2.6-cp38-cp38-win32.whl", hash = "sha256:89221ec6d6026f8ae859c09b9718799fea22c0e8da8b766b0b2c9a9ba2db326b"},
|
||||||
|
{file = "ruamel.yaml.clib-0.2.6-cp38-cp38-win_amd64.whl", hash = "sha256:31ea73e564a7b5fbbe8188ab8b334393e06d997914a4e184975348f204790277"},
|
||||||
|
{file = "ruamel.yaml.clib-0.2.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:dc6a613d6c74eef5a14a214d433d06291526145431c3b964f5e16529b1842bed"},
|
||||||
|
{file = "ruamel.yaml.clib-0.2.6-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:1866cf2c284a03b9524a5cc00daca56d80057c5ce3cdc86a52020f4c720856f0"},
|
||||||
|
{file = "ruamel.yaml.clib-0.2.6-cp39-cp39-win32.whl", hash = "sha256:3fb9575a5acd13031c57a62cc7823e5d2ff8bc3835ba4d94b921b4e6ee664104"},
|
||||||
|
{file = "ruamel.yaml.clib-0.2.6-cp39-cp39-win_amd64.whl", hash = "sha256:825d5fccef6da42f3c8eccd4281af399f21c02b32d98e113dbc631ea6a6ecbc7"},
|
||||||
|
{file = "ruamel.yaml.clib-0.2.6.tar.gz", hash = "sha256:4ff604ce439abb20794f05613c374759ce10e3595d1867764dd1ae675b85acbd"},
|
||||||
|
]
|
||||||
|
six = [
|
||||||
|
{file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
|
||||||
|
{file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
|
||||||
|
]
|
||||||
|
toml = [
|
||||||
|
{file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"},
|
||||||
|
{file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"},
|
||||||
|
]
|
||||||
tomli = [
|
tomli = [
|
||||||
{file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"},
|
{file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"},
|
||||||
{file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"},
|
{file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"},
|
||||||
|
@ -189,3 +524,7 @@ typer = [
|
||||||
{file = "typer-0.4.1-py3-none-any.whl", hash = "sha256:e8467f0ebac0c81366c2168d6ad9f888efdfb6d4e1d3d5b4a004f46fa444b5c3"},
|
{file = "typer-0.4.1-py3-none-any.whl", hash = "sha256:e8467f0ebac0c81366c2168d6ad9f888efdfb6d4e1d3d5b4a004f46fa444b5c3"},
|
||||||
{file = "typer-0.4.1.tar.gz", hash = "sha256:5646aef0d936b2c761a10393f0384ee6b5c7fe0bb3e5cd710b17134ca1d99cff"},
|
{file = "typer-0.4.1.tar.gz", hash = "sha256:5646aef0d936b2c761a10393f0384ee6b5c7fe0bb3e5cd710b17134ca1d99cff"},
|
||||||
]
|
]
|
||||||
|
virtualenv = [
|
||||||
|
{file = "virtualenv-20.14.1-py2.py3-none-any.whl", hash = "sha256:e617f16e25b42eb4f6e74096b9c9e37713cf10bf30168fb4a739f3fa8f898a3a"},
|
||||||
|
{file = "virtualenv-20.14.1.tar.gz", hash = "sha256:ef589a79795589aada0c1c5b319486797c03b67ac3984c48c669c0e4f50df3a5"},
|
||||||
|
]
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = "compose-viz"
|
name = "compose-viz"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
description = "A docker-compose/podman-compose graph visualization tool that allows you to gernerate graph in DOT format or PNG."
|
description = "A compose file visualization tool that supports compose-spec and allows you to gernerate graph in DOT format or PNG."
|
||||||
authors = ["Xyphuz Wu <xyphuzwu@gmail.com>"]
|
authors = ["Xyphuz Wu <xyphuzwu@gmail.com>"]
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
@ -14,9 +14,15 @@ include = [
|
||||||
[tool.poetry.dependencies]
|
[tool.poetry.dependencies]
|
||||||
python = "^3.9"
|
python = "^3.9"
|
||||||
typer = "^0.4.1"
|
typer = "^0.4.1"
|
||||||
|
PyYAML = "^6.0"
|
||||||
|
graphviz = "^0.20"
|
||||||
|
"ruamel.yaml" = "^0.17.21"
|
||||||
|
|
||||||
[tool.poetry.dev-dependencies]
|
[tool.poetry.dev-dependencies]
|
||||||
pytest = "^7.1.2"
|
pytest = "^7.1.2"
|
||||||
|
pre-commit = "^2.19.0"
|
||||||
|
coverage = "^6.3.3"
|
||||||
|
pytest-cov = "^3.0.0"
|
||||||
|
|
||||||
[build-system]
|
[build-system]
|
||||||
requires = ["poetry-core>=1.0.0"]
|
requires = ["poetry-core>=1.0.0"]
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
services:
|
|
||||||
base:
|
|
||||||
image: busybox
|
|
||||||
user: root
|
|
||||||
common:
|
|
||||||
image: busybox
|
|
||||||
extends:
|
|
||||||
service: base
|
|
||||||
cli:
|
|
||||||
extends:
|
|
||||||
service: common
|
|
|
@ -1,30 +0,0 @@
|
||||||
services:
|
|
||||||
frontend:
|
|
||||||
image: awesome/webapp
|
|
||||||
networks:
|
|
||||||
- front-tier
|
|
||||||
- back-tier
|
|
||||||
|
|
||||||
monitoring:
|
|
||||||
image: awesome/monitoring
|
|
||||||
networks:
|
|
||||||
- admin
|
|
||||||
extends:
|
|
||||||
service: frontend
|
|
||||||
|
|
||||||
backend:
|
|
||||||
image: awesome/backend
|
|
||||||
networks:
|
|
||||||
back-tier:
|
|
||||||
aliases:
|
|
||||||
- database
|
|
||||||
admin:
|
|
||||||
aliases:
|
|
||||||
- mysql
|
|
||||||
extends:
|
|
||||||
service: frontend
|
|
||||||
|
|
||||||
networks:
|
|
||||||
front-tier:
|
|
||||||
back-tier:
|
|
||||||
admin:
|
|
|
@ -1,8 +0,0 @@
|
||||||
version: "3.9"
|
|
||||||
services:
|
|
||||||
web:
|
|
||||||
build: .
|
|
||||||
ports:
|
|
||||||
- "8000:5000"
|
|
||||||
redis:
|
|
||||||
image: "redis:alpine"
|
|
|
@ -1,32 +0,0 @@
|
||||||
services:
|
|
||||||
frontend:
|
|
||||||
image: awesome/webapp
|
|
||||||
ports:
|
|
||||||
- "8000:5000"
|
|
||||||
networks:
|
|
||||||
- front-tier
|
|
||||||
- back-tier
|
|
||||||
|
|
||||||
monitoring:
|
|
||||||
image: awesome/monitoring
|
|
||||||
ports:
|
|
||||||
- "8000:5001"
|
|
||||||
networks:
|
|
||||||
- admin
|
|
||||||
|
|
||||||
backend:
|
|
||||||
image: awesome/backend
|
|
||||||
ports:
|
|
||||||
- "8000:5010"
|
|
||||||
networks:
|
|
||||||
back-tier:
|
|
||||||
aliases:
|
|
||||||
- database
|
|
||||||
admin:
|
|
||||||
aliases:
|
|
||||||
- mysql
|
|
||||||
|
|
||||||
networks:
|
|
||||||
front-tier:
|
|
||||||
back-tier:
|
|
||||||
admin:
|
|
|
@ -1,17 +0,0 @@
|
||||||
services:
|
|
||||||
frontend:
|
|
||||||
image: awesome/webapp
|
|
||||||
ports:
|
|
||||||
- "8000:5000"
|
|
||||||
|
|
||||||
monitoring:
|
|
||||||
image: awesome/monitoring
|
|
||||||
extends:
|
|
||||||
service: frontend
|
|
||||||
|
|
||||||
backend:
|
|
||||||
image: awesome/backend
|
|
||||||
extends:
|
|
||||||
service: frontend
|
|
||||||
ports:
|
|
||||||
- "8000:5001"
|
|
|
@ -1,34 +0,0 @@
|
||||||
services:
|
|
||||||
frontend:
|
|
||||||
image: awesome/webapp
|
|
||||||
networks:
|
|
||||||
- front-tier
|
|
||||||
- back-tier
|
|
||||||
ports:
|
|
||||||
- "8000:5000"
|
|
||||||
|
|
||||||
monitoring:
|
|
||||||
image: awesome/monitoring
|
|
||||||
networks:
|
|
||||||
- admin
|
|
||||||
extends:
|
|
||||||
service: frontend
|
|
||||||
|
|
||||||
backend:
|
|
||||||
image: awesome/backend
|
|
||||||
networks:
|
|
||||||
back-tier:
|
|
||||||
aliases:
|
|
||||||
- database
|
|
||||||
admin:
|
|
||||||
aliases:
|
|
||||||
- mysql
|
|
||||||
extends:
|
|
||||||
service: frontend
|
|
||||||
ports:
|
|
||||||
- "8000:5001"
|
|
||||||
|
|
||||||
networks:
|
|
||||||
front-tier:
|
|
||||||
back-tier:
|
|
||||||
admin:
|
|
|
@ -1,10 +0,0 @@
|
||||||
services:
|
|
||||||
web:
|
|
||||||
build: .
|
|
||||||
depends_on:
|
|
||||||
- db
|
|
||||||
- redis
|
|
||||||
redis:
|
|
||||||
image: redis
|
|
||||||
db:
|
|
||||||
image: postgres
|
|
|
@ -1,29 +0,0 @@
|
||||||
services:
|
|
||||||
frontend:
|
|
||||||
image: awesome/webapp
|
|
||||||
networks:
|
|
||||||
- front-tier
|
|
||||||
- back-tier
|
|
||||||
depends_on:
|
|
||||||
- monitoring
|
|
||||||
- backend
|
|
||||||
|
|
||||||
monitoring:
|
|
||||||
image: awesome/monitoring
|
|
||||||
networks:
|
|
||||||
- admin
|
|
||||||
|
|
||||||
backend:
|
|
||||||
image: awesome/backend
|
|
||||||
networks:
|
|
||||||
back-tier:
|
|
||||||
aliases:
|
|
||||||
- database
|
|
||||||
admin:
|
|
||||||
aliases:
|
|
||||||
- mysql
|
|
||||||
|
|
||||||
networks:
|
|
||||||
front-tier:
|
|
||||||
back-tier:
|
|
||||||
admin:
|
|
|
@ -1,12 +0,0 @@
|
||||||
services:
|
|
||||||
web:
|
|
||||||
build: .
|
|
||||||
depends_on:
|
|
||||||
- db
|
|
||||||
- redis
|
|
||||||
extends:
|
|
||||||
service: redis
|
|
||||||
redis:
|
|
||||||
image: redis
|
|
||||||
db:
|
|
||||||
image: postgres
|
|
|
@ -1,31 +0,0 @@
|
||||||
services:
|
|
||||||
frontend:
|
|
||||||
image: awesome/webapp
|
|
||||||
networks:
|
|
||||||
- front-tier
|
|
||||||
- back-tier
|
|
||||||
depends_on:
|
|
||||||
- monitoring
|
|
||||||
- backend
|
|
||||||
extends:
|
|
||||||
service: backend
|
|
||||||
|
|
||||||
monitoring:
|
|
||||||
image: awesome/monitoring
|
|
||||||
networks:
|
|
||||||
- admin
|
|
||||||
|
|
||||||
backend:
|
|
||||||
image: awesome/backend
|
|
||||||
networks:
|
|
||||||
back-tier:
|
|
||||||
aliases:
|
|
||||||
- database
|
|
||||||
admin:
|
|
||||||
aliases:
|
|
||||||
- mysql
|
|
||||||
|
|
||||||
networks:
|
|
||||||
front-tier:
|
|
||||||
back-tier:
|
|
||||||
admin:
|
|
|
@ -1,17 +0,0 @@
|
||||||
services:
|
|
||||||
frontend:
|
|
||||||
image: awesome/webapp
|
|
||||||
ports:
|
|
||||||
- "8000:5000"
|
|
||||||
|
|
||||||
monitoring:
|
|
||||||
image: awesome/monitoring
|
|
||||||
depends_on:
|
|
||||||
- backend
|
|
||||||
ports:
|
|
||||||
- "8000:5010"
|
|
||||||
|
|
||||||
backend:
|
|
||||||
image: awesome/backend
|
|
||||||
ports:
|
|
||||||
- "8000:5001"
|
|
|
@ -1,30 +0,0 @@
|
||||||
services:
|
|
||||||
frontend:
|
|
||||||
image: awesome/webapp
|
|
||||||
networks:
|
|
||||||
- front-tier
|
|
||||||
- back-tier
|
|
||||||
|
|
||||||
monitoring:
|
|
||||||
image: awesome/monitoring
|
|
||||||
networks:
|
|
||||||
- admin
|
|
||||||
depends_on:
|
|
||||||
- backend
|
|
||||||
ports:
|
|
||||||
- "8000:5010"
|
|
||||||
|
|
||||||
backend:
|
|
||||||
image: awesome/backend
|
|
||||||
networks:
|
|
||||||
back-tier:
|
|
||||||
aliases:
|
|
||||||
- database
|
|
||||||
admin:
|
|
||||||
aliases:
|
|
||||||
- mysql
|
|
||||||
|
|
||||||
networks:
|
|
||||||
front-tier:
|
|
||||||
back-tier:
|
|
||||||
admin:
|
|
|
@ -1,21 +0,0 @@
|
||||||
services:
|
|
||||||
frontend:
|
|
||||||
image: awesome/webapp
|
|
||||||
ports:
|
|
||||||
- "8000:5000"
|
|
||||||
|
|
||||||
monitoring:
|
|
||||||
image: awesome/monitoring
|
|
||||||
depends_on:
|
|
||||||
- backend
|
|
||||||
extends:
|
|
||||||
service: frontend
|
|
||||||
ports:
|
|
||||||
- "8000:5010"
|
|
||||||
|
|
||||||
backend:
|
|
||||||
image: awesome/backend
|
|
||||||
extends:
|
|
||||||
service: frontend
|
|
||||||
ports:
|
|
||||||
- "8000:5001"
|
|
|
@ -1,32 +0,0 @@
|
||||||
services:
|
|
||||||
frontend:
|
|
||||||
image: awesome/webapp
|
|
||||||
networks:
|
|
||||||
- front-tier
|
|
||||||
- back-tier
|
|
||||||
|
|
||||||
monitoring:
|
|
||||||
image: awesome/monitoring
|
|
||||||
networks:
|
|
||||||
- admin
|
|
||||||
depends_on:
|
|
||||||
- backend
|
|
||||||
extends:
|
|
||||||
service: frontend
|
|
||||||
ports:
|
|
||||||
- "8000:5010"
|
|
||||||
|
|
||||||
backend:
|
|
||||||
image: awesome/backend
|
|
||||||
networks:
|
|
||||||
back-tier:
|
|
||||||
aliases:
|
|
||||||
- database
|
|
||||||
admin:
|
|
||||||
aliases:
|
|
||||||
- mysql
|
|
||||||
|
|
||||||
networks:
|
|
||||||
front-tier:
|
|
||||||
back-tier:
|
|
||||||
admin:
|
|
|
@ -1,15 +0,0 @@
|
||||||
services:
|
|
||||||
backend:
|
|
||||||
image: awesome/backend
|
|
||||||
volumes:
|
|
||||||
- type: volume
|
|
||||||
source: db-data
|
|
||||||
target: /data
|
|
||||||
volume:
|
|
||||||
nocopy: true
|
|
||||||
- type: bind
|
|
||||||
source: /var/run/postgres/postgres.sock
|
|
||||||
target: /var/run/postgres/postgres.sock
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
db-data:
|
|
|
@ -1,37 +0,0 @@
|
||||||
services:
|
|
||||||
frontend:
|
|
||||||
image: awesome/webapp
|
|
||||||
networks:
|
|
||||||
- front-tier
|
|
||||||
- back-tier
|
|
||||||
|
|
||||||
monitoring:
|
|
||||||
image: awesome/monitoring
|
|
||||||
networks:
|
|
||||||
- admin
|
|
||||||
|
|
||||||
backend:
|
|
||||||
image: awesome/backend
|
|
||||||
networks:
|
|
||||||
back-tier:
|
|
||||||
aliases:
|
|
||||||
- database
|
|
||||||
admin:
|
|
||||||
aliases:
|
|
||||||
- mysql
|
|
||||||
volumes:
|
|
||||||
- type: volume
|
|
||||||
source: db-data
|
|
||||||
target: /data
|
|
||||||
volume:
|
|
||||||
nocopy: true
|
|
||||||
- type: bind
|
|
||||||
source: /var/run/postgres/postgres.sock
|
|
||||||
target: /var/run/postgres/postgres.sock
|
|
||||||
|
|
||||||
networks:
|
|
||||||
front-tier:
|
|
||||||
back-tier:
|
|
||||||
admin:
|
|
||||||
volumes:
|
|
||||||
db-data:
|
|
|
@ -1,13 +0,0 @@
|
||||||
services:
|
|
||||||
common:
|
|
||||||
image: busybox
|
|
||||||
volumes:
|
|
||||||
- common-volume:/var/lib/backup/data:rw
|
|
||||||
cli:
|
|
||||||
extends:
|
|
||||||
service: common
|
|
||||||
volumes:
|
|
||||||
- cli-volume:/var/lib/backup/data:ro
|
|
||||||
volumes:
|
|
||||||
common-volume:
|
|
||||||
cli-volume:
|
|
|
@ -1,39 +0,0 @@
|
||||||
services:
|
|
||||||
frontend:
|
|
||||||
image: awesome/webapp
|
|
||||||
networks:
|
|
||||||
- front-tier
|
|
||||||
- back-tier
|
|
||||||
|
|
||||||
monitoring:
|
|
||||||
image: awesome/monitoring
|
|
||||||
networks:
|
|
||||||
- admin
|
|
||||||
|
|
||||||
backend:
|
|
||||||
image: awesome/backend
|
|
||||||
networks:
|
|
||||||
back-tier:
|
|
||||||
aliases:
|
|
||||||
- database
|
|
||||||
admin:
|
|
||||||
aliases:
|
|
||||||
- mysql
|
|
||||||
volumes:
|
|
||||||
- type: volume
|
|
||||||
source: db-data
|
|
||||||
target: /data
|
|
||||||
volume:
|
|
||||||
nocopy: true
|
|
||||||
- type: bind
|
|
||||||
source: /var/run/postgres/postgres.sock
|
|
||||||
target: /var/run/postgres/postgres.sock
|
|
||||||
extends:
|
|
||||||
service: monitoring
|
|
||||||
|
|
||||||
networks:
|
|
||||||
front-tier:
|
|
||||||
back-tier:
|
|
||||||
admin:
|
|
||||||
volumes:
|
|
||||||
db-data:
|
|
|
@ -1,16 +0,0 @@
|
||||||
services:
|
|
||||||
backend:
|
|
||||||
image: awesome/backend
|
|
||||||
volumes:
|
|
||||||
- type: volume
|
|
||||||
source: db-data
|
|
||||||
target: /data
|
|
||||||
volume:
|
|
||||||
nocopy: true
|
|
||||||
- type: bind
|
|
||||||
source: /var/run/postgres/postgres.sock
|
|
||||||
target: /var/run/postgres/postgres.sock
|
|
||||||
ports:
|
|
||||||
- "8000:5000"
|
|
||||||
volumes:
|
|
||||||
db-data:
|
|
|
@ -1,39 +0,0 @@
|
||||||
services:
|
|
||||||
frontend:
|
|
||||||
image: awesome/webapp
|
|
||||||
networks:
|
|
||||||
- front-tier
|
|
||||||
- back-tier
|
|
||||||
|
|
||||||
monitoring:
|
|
||||||
image: awesome/monitoring
|
|
||||||
networks:
|
|
||||||
- admin
|
|
||||||
|
|
||||||
backend:
|
|
||||||
image: awesome/backend
|
|
||||||
networks:
|
|
||||||
back-tier:
|
|
||||||
aliases:
|
|
||||||
- database
|
|
||||||
admin:
|
|
||||||
aliases:
|
|
||||||
- mysql
|
|
||||||
volumes:
|
|
||||||
- type: volume
|
|
||||||
source: db-data
|
|
||||||
target: /data
|
|
||||||
volume:
|
|
||||||
nocopy: true
|
|
||||||
- type: bind
|
|
||||||
source: /var/run/postgres/postgres.sock
|
|
||||||
target: /var/run/postgres/postgres.sock
|
|
||||||
ports:
|
|
||||||
- "8000:5000"
|
|
||||||
|
|
||||||
networks:
|
|
||||||
front-tier:
|
|
||||||
back-tier:
|
|
||||||
admin:
|
|
||||||
volumes:
|
|
||||||
db-data:
|
|
|
@ -1,24 +0,0 @@
|
||||||
services:
|
|
||||||
frontend:
|
|
||||||
image: awesome/webapp
|
|
||||||
|
|
||||||
monitoring:
|
|
||||||
image: awesome/monitoring
|
|
||||||
|
|
||||||
backend:
|
|
||||||
image: awesome/backend
|
|
||||||
volumes:
|
|
||||||
- type: volume
|
|
||||||
source: db-data
|
|
||||||
target: /data
|
|
||||||
volume:
|
|
||||||
nocopy: true
|
|
||||||
- type: bind
|
|
||||||
source: /var/run/postgres/postgres.sock
|
|
||||||
target: /var/run/postgres/postgres.sock
|
|
||||||
extends:
|
|
||||||
service: monitoring
|
|
||||||
ports:
|
|
||||||
- "8000:5000"
|
|
||||||
volumes:
|
|
||||||
db-data:
|
|
|
@ -1,41 +0,0 @@
|
||||||
services:
|
|
||||||
frontend:
|
|
||||||
image: awesome/webapp
|
|
||||||
networks:
|
|
||||||
- front-tier
|
|
||||||
- back-tier
|
|
||||||
|
|
||||||
monitoring:
|
|
||||||
image: awesome/monitoring
|
|
||||||
networks:
|
|
||||||
- admin
|
|
||||||
|
|
||||||
backend:
|
|
||||||
image: awesome/backend
|
|
||||||
networks:
|
|
||||||
back-tier:
|
|
||||||
aliases:
|
|
||||||
- database
|
|
||||||
admin:
|
|
||||||
aliases:
|
|
||||||
- mysql
|
|
||||||
volumes:
|
|
||||||
- type: volume
|
|
||||||
source: db-data
|
|
||||||
target: /data
|
|
||||||
volume:
|
|
||||||
nocopy: true
|
|
||||||
- type: bind
|
|
||||||
source: /var/run/postgres/postgres.sock
|
|
||||||
target: /var/run/postgres/postgres.sock
|
|
||||||
extends:
|
|
||||||
service: monitoring
|
|
||||||
ports:
|
|
||||||
- "8000:5000"
|
|
||||||
|
|
||||||
networks:
|
|
||||||
front-tier:
|
|
||||||
back-tier:
|
|
||||||
admin:
|
|
||||||
volumes:
|
|
||||||
db-data:
|
|
|
@ -1,22 +0,0 @@
|
||||||
services:
|
|
||||||
frontend:
|
|
||||||
image: awesome/webapp
|
|
||||||
|
|
||||||
monitoring:
|
|
||||||
image: awesome/monitoring
|
|
||||||
depends_on:
|
|
||||||
- backend
|
|
||||||
volumes:
|
|
||||||
- type: volume
|
|
||||||
source: db-data
|
|
||||||
target: /data
|
|
||||||
volume:
|
|
||||||
nocopy: true
|
|
||||||
- type: bind
|
|
||||||
source: /var/run/postgres/postgres.sock
|
|
||||||
target: /var/run/postgres/postgres.sock
|
|
||||||
|
|
||||||
backend:
|
|
||||||
image: awesome/backend
|
|
||||||
volumes:
|
|
||||||
db-data:
|
|
|
@ -1,40 +0,0 @@
|
||||||
services:
|
|
||||||
frontend:
|
|
||||||
image: awesome/webapp
|
|
||||||
networks:
|
|
||||||
- front-tier
|
|
||||||
- back-tier
|
|
||||||
|
|
||||||
monitoring:
|
|
||||||
image: awesome/monitoring
|
|
||||||
networks:
|
|
||||||
- admin
|
|
||||||
|
|
||||||
|
|
||||||
backend:
|
|
||||||
image: awesome/backend
|
|
||||||
networks:
|
|
||||||
back-tier:
|
|
||||||
aliases:
|
|
||||||
- database
|
|
||||||
admin:
|
|
||||||
aliases:
|
|
||||||
- mysql
|
|
||||||
volumes:
|
|
||||||
- type: volume
|
|
||||||
source: db-data
|
|
||||||
target: /data
|
|
||||||
volume:
|
|
||||||
nocopy: true
|
|
||||||
- type: bind
|
|
||||||
source: /var/run/postgres/postgres.sock
|
|
||||||
target: /var/run/postgres/postgres.sock
|
|
||||||
depends_on:
|
|
||||||
- monitoring
|
|
||||||
|
|
||||||
networks:
|
|
||||||
front-tier:
|
|
||||||
back-tier:
|
|
||||||
admin:
|
|
||||||
volumes:
|
|
||||||
db-data:
|
|
|
@ -1,26 +0,0 @@
|
||||||
services:
|
|
||||||
frontend:
|
|
||||||
image: awesome/webapp
|
|
||||||
|
|
||||||
monitoring:
|
|
||||||
image: awesome/monitoring
|
|
||||||
|
|
||||||
|
|
||||||
backend:
|
|
||||||
image: awesome/backend
|
|
||||||
volumes:
|
|
||||||
- type: volume
|
|
||||||
source: db-data
|
|
||||||
target: /data
|
|
||||||
volume:
|
|
||||||
nocopy: true
|
|
||||||
- type: bind
|
|
||||||
source: /var/run/postgres/postgres.sock
|
|
||||||
target: /var/run/postgres/postgres.sock
|
|
||||||
depends_on:
|
|
||||||
- monitoring
|
|
||||||
extends:
|
|
||||||
service: frontend
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
db-data:
|
|
|
@ -1,42 +0,0 @@
|
||||||
services:
|
|
||||||
frontend:
|
|
||||||
image: awesome/webapp
|
|
||||||
networks:
|
|
||||||
- front-tier
|
|
||||||
- back-tier
|
|
||||||
|
|
||||||
monitoring:
|
|
||||||
image: awesome/monitoring
|
|
||||||
networks:
|
|
||||||
- admin
|
|
||||||
|
|
||||||
|
|
||||||
backend:
|
|
||||||
image: awesome/backend
|
|
||||||
networks:
|
|
||||||
back-tier:
|
|
||||||
aliases:
|
|
||||||
- database
|
|
||||||
admin:
|
|
||||||
aliases:
|
|
||||||
- mysql
|
|
||||||
volumes:
|
|
||||||
- type: volume
|
|
||||||
source: db-data
|
|
||||||
target: /data
|
|
||||||
volume:
|
|
||||||
nocopy: true
|
|
||||||
- type: bind
|
|
||||||
source: /var/run/postgres/postgres.sock
|
|
||||||
target: /var/run/postgres/postgres.sock
|
|
||||||
depends_on:
|
|
||||||
- monitoring
|
|
||||||
extends:
|
|
||||||
service: frontend
|
|
||||||
|
|
||||||
networks:
|
|
||||||
front-tier:
|
|
||||||
back-tier:
|
|
||||||
admin:
|
|
||||||
volumes:
|
|
||||||
db-data:
|
|
|
@ -1,28 +0,0 @@
|
||||||
services:
|
|
||||||
frontend:
|
|
||||||
image: awesome/webapp
|
|
||||||
ports:
|
|
||||||
- "8000:5000"
|
|
||||||
|
|
||||||
monitoring:
|
|
||||||
image: awesome/monitoring
|
|
||||||
depends_on:
|
|
||||||
- backend
|
|
||||||
ports:
|
|
||||||
- "8000:5010"
|
|
||||||
volumes:
|
|
||||||
- type: volume
|
|
||||||
source: db-data
|
|
||||||
target: /data
|
|
||||||
volume:
|
|
||||||
nocopy: true
|
|
||||||
- type: bind
|
|
||||||
source: /var/run/postgres/postgres.sock
|
|
||||||
target: /var/run/postgres/postgres.sock
|
|
||||||
|
|
||||||
backend:
|
|
||||||
image: awesome/backend
|
|
||||||
ports:
|
|
||||||
- "8000:5001"
|
|
||||||
volumes:
|
|
||||||
db-data:
|
|
|
@ -1,74 +0,0 @@
|
||||||
services:
|
|
||||||
vote:
|
|
||||||
build: ./
|
|
||||||
# use python rather than gunicorn for local dev
|
|
||||||
command: python app.py
|
|
||||||
depends_on:
|
|
||||||
redis:
|
|
||||||
condition: service_healthy
|
|
||||||
volumes:
|
|
||||||
- app
|
|
||||||
ports:
|
|
||||||
- "5000:80"
|
|
||||||
networks:
|
|
||||||
- front-tier
|
|
||||||
- back-tier
|
|
||||||
|
|
||||||
result:
|
|
||||||
build: ./
|
|
||||||
# use nodemon rather than node for local dev
|
|
||||||
command: nodemon server.js
|
|
||||||
depends_on:
|
|
||||||
db:
|
|
||||||
condition: service_healthy
|
|
||||||
volumes:
|
|
||||||
- app
|
|
||||||
ports:
|
|
||||||
- "5001:80"
|
|
||||||
- "5858:5858"
|
|
||||||
networks:
|
|
||||||
- front-tier
|
|
||||||
- back-tier
|
|
||||||
|
|
||||||
worker:
|
|
||||||
build:
|
|
||||||
context: ./
|
|
||||||
depends_on:
|
|
||||||
redis:
|
|
||||||
condition: service_healthy
|
|
||||||
db:
|
|
||||||
condition: service_healthy
|
|
||||||
networks:
|
|
||||||
- back-tier
|
|
||||||
|
|
||||||
redis:
|
|
||||||
image: redis:5.0-alpine3.10
|
|
||||||
volumes:
|
|
||||||
- "./healthchecks:/healthchecks"
|
|
||||||
healthcheck:
|
|
||||||
test: /healthchecks/redis.sh
|
|
||||||
interval: "5s"
|
|
||||||
ports: ["6379"]
|
|
||||||
networks:
|
|
||||||
- back-tier
|
|
||||||
|
|
||||||
db:
|
|
||||||
image: postgres:9.4
|
|
||||||
environment:
|
|
||||||
POSTGRES_USER: "postgres"
|
|
||||||
POSTGRES_PASSWORD: "postgres"
|
|
||||||
volumes:
|
|
||||||
- "db-data:/var/lib/postgresql/data"
|
|
||||||
- "./healthchecks:/healthchecks"
|
|
||||||
healthcheck:
|
|
||||||
test: /healthchecks/postgres.sh
|
|
||||||
interval: "5s"
|
|
||||||
networks:
|
|
||||||
- back-tier
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
db-data:
|
|
||||||
|
|
||||||
networks:
|
|
||||||
front-tier:
|
|
||||||
back-tier:
|
|
|
@ -1,30 +0,0 @@
|
||||||
services:
|
|
||||||
frontend:
|
|
||||||
image: awesome/webapp
|
|
||||||
|
|
||||||
|
|
||||||
monitoring:
|
|
||||||
image: awesome/monitoring
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
backend:
|
|
||||||
image: awesome/backend
|
|
||||||
volumes:
|
|
||||||
- type: volume
|
|
||||||
source: db-data
|
|
||||||
target: /data
|
|
||||||
volume:
|
|
||||||
nocopy: true
|
|
||||||
- type: bind
|
|
||||||
source: /var/run/postgres/postgres.sock
|
|
||||||
target: /var/run/postgres/postgres.sock
|
|
||||||
depends_on:
|
|
||||||
- monitoring
|
|
||||||
extends:
|
|
||||||
service: frontend
|
|
||||||
ports:
|
|
||||||
- "8000:5010"
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
db-data:
|
|
|
@ -1,44 +0,0 @@
|
||||||
services:
|
|
||||||
frontend:
|
|
||||||
image: awesome/webapp
|
|
||||||
networks:
|
|
||||||
- front-tier
|
|
||||||
- back-tier
|
|
||||||
|
|
||||||
monitoring:
|
|
||||||
image: awesome/monitoring
|
|
||||||
networks:
|
|
||||||
- admin
|
|
||||||
|
|
||||||
|
|
||||||
backend:
|
|
||||||
image: awesome/backend
|
|
||||||
networks:
|
|
||||||
back-tier:
|
|
||||||
aliases:
|
|
||||||
- database
|
|
||||||
admin:
|
|
||||||
aliases:
|
|
||||||
- mysql
|
|
||||||
volumes:
|
|
||||||
- type: volume
|
|
||||||
source: db-data
|
|
||||||
target: /data
|
|
||||||
volume:
|
|
||||||
nocopy: true
|
|
||||||
- type: bind
|
|
||||||
source: /var/run/postgres/postgres.sock
|
|
||||||
target: /var/run/postgres/postgres.sock
|
|
||||||
depends_on:
|
|
||||||
- monitoring
|
|
||||||
extends:
|
|
||||||
service: frontend
|
|
||||||
ports:
|
|
||||||
- "8000:5010"
|
|
||||||
|
|
||||||
networks:
|
|
||||||
front-tier:
|
|
||||||
back-tier:
|
|
||||||
admin:
|
|
||||||
volumes:
|
|
||||||
db-data:
|
|
|
@ -1,31 +0,0 @@
|
||||||
services:
|
|
||||||
frontend:
|
|
||||||
image: awesome/webapp
|
|
||||||
networks:
|
|
||||||
- front-tier
|
|
||||||
- back-tier
|
|
||||||
|
|
||||||
monitoring:
|
|
||||||
image: awesome/monitoring
|
|
||||||
networks:
|
|
||||||
- admin
|
|
||||||
|
|
||||||
|
|
||||||
backend:
|
|
||||||
image: awesome/backend
|
|
||||||
networks:
|
|
||||||
back-tier:
|
|
||||||
aliases:
|
|
||||||
- database
|
|
||||||
admin:
|
|
||||||
aliases:
|
|
||||||
- mysql
|
|
||||||
links:
|
|
||||||
- "db:database"
|
|
||||||
db:
|
|
||||||
image: postgres
|
|
||||||
|
|
||||||
networks:
|
|
||||||
front-tier:
|
|
||||||
back-tier:
|
|
||||||
admin:
|
|
|
@ -1,16 +0,0 @@
|
||||||
services:
|
|
||||||
frontend:
|
|
||||||
image: awesome/webapp
|
|
||||||
|
|
||||||
monitoring:
|
|
||||||
image: awesome/monitoring
|
|
||||||
|
|
||||||
|
|
||||||
backend:
|
|
||||||
image: awesome/backend
|
|
||||||
extends:
|
|
||||||
service: frontend
|
|
||||||
links:
|
|
||||||
- "db:database"
|
|
||||||
db:
|
|
||||||
image: postgres
|
|
|
@ -1,33 +0,0 @@
|
||||||
services:
|
|
||||||
frontend:
|
|
||||||
image: awesome/webapp
|
|
||||||
networks:
|
|
||||||
- front-tier
|
|
||||||
- back-tier
|
|
||||||
|
|
||||||
monitoring:
|
|
||||||
image: awesome/monitoring
|
|
||||||
networks:
|
|
||||||
- admin
|
|
||||||
|
|
||||||
|
|
||||||
backend:
|
|
||||||
image: awesome/backend
|
|
||||||
networks:
|
|
||||||
back-tier:
|
|
||||||
aliases:
|
|
||||||
- database
|
|
||||||
admin:
|
|
||||||
aliases:
|
|
||||||
- mysql
|
|
||||||
extends:
|
|
||||||
service: frontend
|
|
||||||
links:
|
|
||||||
- "db:database"
|
|
||||||
db:
|
|
||||||
image: postgres
|
|
||||||
|
|
||||||
networks:
|
|
||||||
front-tier:
|
|
||||||
back-tier:
|
|
||||||
admin:
|
|
|
@ -1,16 +0,0 @@
|
||||||
services:
|
|
||||||
frontend:
|
|
||||||
image: awesome/webapp
|
|
||||||
|
|
||||||
monitoring:
|
|
||||||
image: awesome/monitoring
|
|
||||||
|
|
||||||
|
|
||||||
backend:
|
|
||||||
image: awesome/backend
|
|
||||||
ports:
|
|
||||||
- "8000:5010"
|
|
||||||
links:
|
|
||||||
- "db:database"
|
|
||||||
db:
|
|
||||||
image: postgres
|
|
|
@ -1,33 +0,0 @@
|
||||||
services:
|
|
||||||
frontend:
|
|
||||||
image: awesome/webapp
|
|
||||||
networks:
|
|
||||||
- front-tier
|
|
||||||
- back-tier
|
|
||||||
|
|
||||||
monitoring:
|
|
||||||
image: awesome/monitoring
|
|
||||||
networks:
|
|
||||||
- admin
|
|
||||||
|
|
||||||
|
|
||||||
backend:
|
|
||||||
image: awesome/backend
|
|
||||||
networks:
|
|
||||||
back-tier:
|
|
||||||
aliases:
|
|
||||||
- database
|
|
||||||
admin:
|
|
||||||
aliases:
|
|
||||||
- mysql
|
|
||||||
ports:
|
|
||||||
- "8000:5010"
|
|
||||||
links:
|
|
||||||
- "db:database"
|
|
||||||
db:
|
|
||||||
image: postgres
|
|
||||||
|
|
||||||
networks:
|
|
||||||
front-tier:
|
|
||||||
back-tier:
|
|
||||||
admin:
|
|
|
@ -1,18 +0,0 @@
|
||||||
services:
|
|
||||||
frontend:
|
|
||||||
image: awesome/webapp
|
|
||||||
|
|
||||||
monitoring:
|
|
||||||
image: awesome/monitoring
|
|
||||||
|
|
||||||
|
|
||||||
backend:
|
|
||||||
image: awesome/backend
|
|
||||||
extends:
|
|
||||||
service: frontend
|
|
||||||
ports:
|
|
||||||
- "8000:5010"
|
|
||||||
links:
|
|
||||||
- "db:database"
|
|
||||||
db:
|
|
||||||
image: postgres
|
|
|
@ -1,35 +0,0 @@
|
||||||
services:
|
|
||||||
frontend:
|
|
||||||
image: awesome/webapp
|
|
||||||
networks:
|
|
||||||
- front-tier
|
|
||||||
- back-tier
|
|
||||||
|
|
||||||
monitoring:
|
|
||||||
image: awesome/monitoring
|
|
||||||
networks:
|
|
||||||
- admin
|
|
||||||
|
|
||||||
|
|
||||||
backend:
|
|
||||||
image: awesome/backend
|
|
||||||
networks:
|
|
||||||
back-tier:
|
|
||||||
aliases:
|
|
||||||
- database
|
|
||||||
admin:
|
|
||||||
aliases:
|
|
||||||
- mysql
|
|
||||||
extends:
|
|
||||||
service: frontend
|
|
||||||
ports:
|
|
||||||
- "8000:5010"
|
|
||||||
links:
|
|
||||||
- "db:database"
|
|
||||||
db:
|
|
||||||
image: postgres
|
|
||||||
|
|
||||||
networks:
|
|
||||||
front-tier:
|
|
||||||
back-tier:
|
|
||||||
admin:
|
|
|
@ -1,16 +0,0 @@
|
||||||
services:
|
|
||||||
frontend:
|
|
||||||
image: awesome/webapp
|
|
||||||
|
|
||||||
monitoring:
|
|
||||||
image: awesome/monitoring
|
|
||||||
|
|
||||||
|
|
||||||
backend:
|
|
||||||
image: awesome/backend
|
|
||||||
depends_on:
|
|
||||||
- monitoring
|
|
||||||
links:
|
|
||||||
- "db:database"
|
|
||||||
db:
|
|
||||||
image: postgres
|
|
|
@ -1,33 +0,0 @@
|
||||||
services:
|
|
||||||
frontend:
|
|
||||||
image: awesome/webapp
|
|
||||||
networks:
|
|
||||||
- front-tier
|
|
||||||
- back-tier
|
|
||||||
|
|
||||||
monitoring:
|
|
||||||
image: awesome/monitoring
|
|
||||||
networks:
|
|
||||||
- admin
|
|
||||||
|
|
||||||
|
|
||||||
backend:
|
|
||||||
image: awesome/backend
|
|
||||||
networks:
|
|
||||||
back-tier:
|
|
||||||
aliases:
|
|
||||||
- database
|
|
||||||
admin:
|
|
||||||
aliases:
|
|
||||||
- mysql
|
|
||||||
depends_on:
|
|
||||||
- monitoring
|
|
||||||
links:
|
|
||||||
- "db:database"
|
|
||||||
db:
|
|
||||||
image: postgres
|
|
||||||
|
|
||||||
networks:
|
|
||||||
front-tier:
|
|
||||||
back-tier:
|
|
||||||
admin:
|
|
|
@ -1,18 +0,0 @@
|
||||||
services:
|
|
||||||
frontend:
|
|
||||||
image: awesome/webapp
|
|
||||||
|
|
||||||
monitoring:
|
|
||||||
image: awesome/monitoring
|
|
||||||
|
|
||||||
|
|
||||||
backend:
|
|
||||||
image: awesome/backend
|
|
||||||
depends_on:
|
|
||||||
- monitoring
|
|
||||||
links:
|
|
||||||
- "db:database"
|
|
||||||
extends:
|
|
||||||
service: frontend
|
|
||||||
db:
|
|
||||||
image: postgres
|
|
|
@ -1,35 +0,0 @@
|
||||||
services:
|
|
||||||
frontend:
|
|
||||||
image: awesome/webapp
|
|
||||||
networks:
|
|
||||||
- front-tier
|
|
||||||
- back-tier
|
|
||||||
|
|
||||||
monitoring:
|
|
||||||
image: awesome/monitoring
|
|
||||||
networks:
|
|
||||||
- admin
|
|
||||||
|
|
||||||
|
|
||||||
backend:
|
|
||||||
image: awesome/backend
|
|
||||||
networks:
|
|
||||||
back-tier:
|
|
||||||
aliases:
|
|
||||||
- database
|
|
||||||
admin:
|
|
||||||
aliases:
|
|
||||||
- mysql
|
|
||||||
depends_on:
|
|
||||||
- monitoring
|
|
||||||
extends:
|
|
||||||
service: frontend
|
|
||||||
links:
|
|
||||||
- "db:database"
|
|
||||||
db:
|
|
||||||
image: postgres
|
|
||||||
|
|
||||||
networks:
|
|
||||||
front-tier:
|
|
||||||
back-tier:
|
|
||||||
admin:
|
|
|
@ -1,18 +0,0 @@
|
||||||
services:
|
|
||||||
frontend:
|
|
||||||
image: awesome/webapp
|
|
||||||
|
|
||||||
monitoring:
|
|
||||||
image: awesome/monitoring
|
|
||||||
|
|
||||||
|
|
||||||
backend:
|
|
||||||
image: awesome/backend
|
|
||||||
depends_on:
|
|
||||||
- monitoring
|
|
||||||
ports:
|
|
||||||
- "8000:5010"
|
|
||||||
links:
|
|
||||||
- "db:database"
|
|
||||||
db:
|
|
||||||
image: postgres
|
|
|
@ -1,35 +0,0 @@
|
||||||
services:
|
|
||||||
frontend:
|
|
||||||
image: awesome/webapp
|
|
||||||
networks:
|
|
||||||
- front-tier
|
|
||||||
- back-tier
|
|
||||||
|
|
||||||
monitoring:
|
|
||||||
image: awesome/monitoring
|
|
||||||
networks:
|
|
||||||
- admin
|
|
||||||
|
|
||||||
|
|
||||||
backend:
|
|
||||||
image: awesome/backend
|
|
||||||
networks:
|
|
||||||
back-tier:
|
|
||||||
aliases:
|
|
||||||
- database
|
|
||||||
admin:
|
|
||||||
aliases:
|
|
||||||
- mysql
|
|
||||||
depends_on:
|
|
||||||
- monitoring
|
|
||||||
ports:
|
|
||||||
- "8000:5010"
|
|
||||||
links:
|
|
||||||
- "db:database"
|
|
||||||
db:
|
|
||||||
image: postgres
|
|
||||||
|
|
||||||
networks:
|
|
||||||
front-tier:
|
|
||||||
back-tier:
|
|
||||||
admin:
|
|
|
@ -1,21 +0,0 @@
|
||||||
services:
|
|
||||||
frontend:
|
|
||||||
image: awesome/webapp
|
|
||||||
|
|
||||||
monitoring:
|
|
||||||
image: awesome/monitoring
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
backend:
|
|
||||||
image: awesome/backend
|
|
||||||
depends_on:
|
|
||||||
- monitoring
|
|
||||||
extends:
|
|
||||||
service: frontend
|
|
||||||
ports:
|
|
||||||
- "8000:5010"
|
|
||||||
links:
|
|
||||||
- "db:database"
|
|
||||||
db:
|
|
||||||
image: postgres
|
|
|
@ -1,37 +0,0 @@
|
||||||
services:
|
|
||||||
frontend:
|
|
||||||
image: awesome/webapp
|
|
||||||
networks:
|
|
||||||
- front-tier
|
|
||||||
- back-tier
|
|
||||||
|
|
||||||
monitoring:
|
|
||||||
image: awesome/monitoring
|
|
||||||
networks:
|
|
||||||
- admin
|
|
||||||
|
|
||||||
|
|
||||||
backend:
|
|
||||||
image: awesome/backend
|
|
||||||
networks:
|
|
||||||
back-tier:
|
|
||||||
aliases:
|
|
||||||
- database
|
|
||||||
admin:
|
|
||||||
aliases:
|
|
||||||
- mysql
|
|
||||||
depends_on:
|
|
||||||
- monitoring
|
|
||||||
extends:
|
|
||||||
service: frontend
|
|
||||||
ports:
|
|
||||||
- "8000:5010"
|
|
||||||
links:
|
|
||||||
- "db:database"
|
|
||||||
db:
|
|
||||||
image: postgres
|
|
||||||
|
|
||||||
networks:
|
|
||||||
front-tier:
|
|
||||||
back-tier:
|
|
||||||
admin:
|
|
|
@ -1,24 +0,0 @@
|
||||||
services:
|
|
||||||
frontend:
|
|
||||||
image: awesome/webapp
|
|
||||||
|
|
||||||
monitoring:
|
|
||||||
image: awesome/monitoring
|
|
||||||
volumes:
|
|
||||||
- type: volume
|
|
||||||
source: db-data
|
|
||||||
target: /data
|
|
||||||
volume:
|
|
||||||
nocopy: true
|
|
||||||
- type: bind
|
|
||||||
source: /var/run/postgres/postgres.sock
|
|
||||||
target: /var/run/postgres/postgres.sock
|
|
||||||
links:
|
|
||||||
- "db:database"
|
|
||||||
|
|
||||||
backend:
|
|
||||||
image: awesome/backend
|
|
||||||
db:
|
|
||||||
image: postgres
|
|
||||||
volumes:
|
|
||||||
db-data:
|
|
|
@ -1,42 +0,0 @@
|
||||||
services:
|
|
||||||
frontend:
|
|
||||||
image: awesome/webapp
|
|
||||||
networks:
|
|
||||||
- front-tier
|
|
||||||
- back-tier
|
|
||||||
|
|
||||||
monitoring:
|
|
||||||
image: awesome/monitoring
|
|
||||||
networks:
|
|
||||||
- admin
|
|
||||||
|
|
||||||
|
|
||||||
backend:
|
|
||||||
image: awesome/backend
|
|
||||||
networks:
|
|
||||||
back-tier:
|
|
||||||
aliases:
|
|
||||||
- database
|
|
||||||
admin:
|
|
||||||
aliases:
|
|
||||||
- mysql
|
|
||||||
volumes:
|
|
||||||
- type: volume
|
|
||||||
source: db-data
|
|
||||||
target: /data
|
|
||||||
volume:
|
|
||||||
nocopy: true
|
|
||||||
- type: bind
|
|
||||||
source: /var/run/postgres/postgres.sock
|
|
||||||
target: /var/run/postgres/postgres.sock
|
|
||||||
links:
|
|
||||||
- "db:database"
|
|
||||||
db:
|
|
||||||
image: postgres
|
|
||||||
|
|
||||||
networks:
|
|
||||||
front-tier:
|
|
||||||
back-tier:
|
|
||||||
admin:
|
|
||||||
volumes:
|
|
||||||
db-data:
|
|
|
@ -1,28 +0,0 @@
|
||||||
services:
|
|
||||||
frontend:
|
|
||||||
image: awesome/webapp
|
|
||||||
|
|
||||||
monitoring:
|
|
||||||
image: awesome/monitoring
|
|
||||||
|
|
||||||
|
|
||||||
backend:
|
|
||||||
image: awesome/backend
|
|
||||||
volumes:
|
|
||||||
- type: volume
|
|
||||||
source: db-data
|
|
||||||
target: /data
|
|
||||||
volume:
|
|
||||||
nocopy: true
|
|
||||||
- type: bind
|
|
||||||
source: /var/run/postgres/postgres.sock
|
|
||||||
target: /var/run/postgres/postgres.sock
|
|
||||||
extends:
|
|
||||||
service: frontend
|
|
||||||
links:
|
|
||||||
- "db:database"
|
|
||||||
db:
|
|
||||||
image: postgres
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
db-data:
|
|
|
@ -1,44 +0,0 @@
|
||||||
services:
|
|
||||||
frontend:
|
|
||||||
image: awesome/webapp
|
|
||||||
networks:
|
|
||||||
- front-tier
|
|
||||||
- back-tier
|
|
||||||
|
|
||||||
monitoring:
|
|
||||||
image: awesome/monitoring
|
|
||||||
networks:
|
|
||||||
- admin
|
|
||||||
|
|
||||||
|
|
||||||
backend:
|
|
||||||
image: awesome/backend
|
|
||||||
networks:
|
|
||||||
back-tier:
|
|
||||||
aliases:
|
|
||||||
- database
|
|
||||||
admin:
|
|
||||||
aliases:
|
|
||||||
- mysql
|
|
||||||
volumes:
|
|
||||||
- type: volume
|
|
||||||
source: db-data
|
|
||||||
target: /data
|
|
||||||
volume:
|
|
||||||
nocopy: true
|
|
||||||
- type: bind
|
|
||||||
source: /var/run/postgres/postgres.sock
|
|
||||||
target: /var/run/postgres/postgres.sock
|
|
||||||
extends:
|
|
||||||
service: frontend
|
|
||||||
links:
|
|
||||||
- "db:database"
|
|
||||||
db:
|
|
||||||
image: postgres
|
|
||||||
|
|
||||||
networks:
|
|
||||||
front-tier:
|
|
||||||
back-tier:
|
|
||||||
admin:
|
|
||||||
volumes:
|
|
||||||
db-data:
|
|
|
@ -1,28 +0,0 @@
|
||||||
services:
|
|
||||||
frontend:
|
|
||||||
image: awesome/webapp
|
|
||||||
|
|
||||||
monitoring:
|
|
||||||
image: awesome/monitoring
|
|
||||||
|
|
||||||
|
|
||||||
backend:
|
|
||||||
image: awesome/backend
|
|
||||||
volumes:
|
|
||||||
- type: volume
|
|
||||||
source: db-data
|
|
||||||
target: /data
|
|
||||||
volume:
|
|
||||||
nocopy: true
|
|
||||||
- type: bind
|
|
||||||
source: /var/run/postgres/postgres.sock
|
|
||||||
target: /var/run/postgres/postgres.sock
|
|
||||||
ports:
|
|
||||||
- "8000:5010"
|
|
||||||
links:
|
|
||||||
- "db:database"
|
|
||||||
db:
|
|
||||||
image: postgres
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
db-data:
|
|
|
@ -1,44 +0,0 @@
|
||||||
services:
|
|
||||||
frontend:
|
|
||||||
image: awesome/webapp
|
|
||||||
networks:
|
|
||||||
- front-tier
|
|
||||||
- back-tier
|
|
||||||
|
|
||||||
monitoring:
|
|
||||||
image: awesome/monitoring
|
|
||||||
networks:
|
|
||||||
- admin
|
|
||||||
|
|
||||||
|
|
||||||
backend:
|
|
||||||
image: awesome/backend
|
|
||||||
networks:
|
|
||||||
back-tier:
|
|
||||||
aliases:
|
|
||||||
- database
|
|
||||||
admin:
|
|
||||||
aliases:
|
|
||||||
- mysql
|
|
||||||
volumes:
|
|
||||||
- type: volume
|
|
||||||
source: db-data
|
|
||||||
target: /data
|
|
||||||
volume:
|
|
||||||
nocopy: true
|
|
||||||
- type: bind
|
|
||||||
source: /var/run/postgres/postgres.sock
|
|
||||||
target: /var/run/postgres/postgres.sock
|
|
||||||
ports:
|
|
||||||
- "8000:5010"
|
|
||||||
links:
|
|
||||||
- "db:database"
|
|
||||||
db:
|
|
||||||
image: postgres
|
|
||||||
|
|
||||||
networks:
|
|
||||||
front-tier:
|
|
||||||
back-tier:
|
|
||||||
admin:
|
|
||||||
volumes:
|
|
||||||
db-data:
|
|
|
@ -1,30 +0,0 @@
|
||||||
services:
|
|
||||||
frontend:
|
|
||||||
image: awesome/webapp
|
|
||||||
|
|
||||||
monitoring:
|
|
||||||
image: awesome/monitoring
|
|
||||||
|
|
||||||
|
|
||||||
backend:
|
|
||||||
image: awesome/backend
|
|
||||||
volumes:
|
|
||||||
- type: volume
|
|
||||||
source: db-data
|
|
||||||
target: /data
|
|
||||||
volume:
|
|
||||||
nocopy: true
|
|
||||||
- type: bind
|
|
||||||
source: /var/run/postgres/postgres.sock
|
|
||||||
target: /var/run/postgres/postgres.sock
|
|
||||||
extends:
|
|
||||||
service: frontend
|
|
||||||
ports:
|
|
||||||
- "8000:5010"
|
|
||||||
links:
|
|
||||||
- "db:database"
|
|
||||||
db:
|
|
||||||
image: postgres
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
db-data:
|
|
|
@ -1,46 +0,0 @@
|
||||||
services:
|
|
||||||
frontend:
|
|
||||||
image: awesome/webapp
|
|
||||||
networks:
|
|
||||||
- front-tier
|
|
||||||
- back-tier
|
|
||||||
|
|
||||||
monitoring:
|
|
||||||
image: awesome/monitoring
|
|
||||||
networks:
|
|
||||||
- admin
|
|
||||||
|
|
||||||
|
|
||||||
backend:
|
|
||||||
image: awesome/backend
|
|
||||||
networks:
|
|
||||||
back-tier:
|
|
||||||
aliases:
|
|
||||||
- database
|
|
||||||
admin:
|
|
||||||
aliases:
|
|
||||||
- mysql
|
|
||||||
volumes:
|
|
||||||
- type: volume
|
|
||||||
source: db-data
|
|
||||||
target: /data
|
|
||||||
volume:
|
|
||||||
nocopy: true
|
|
||||||
- type: bind
|
|
||||||
source: /var/run/postgres/postgres.sock
|
|
||||||
target: /var/run/postgres/postgres.sock
|
|
||||||
extends:
|
|
||||||
service: frontend
|
|
||||||
ports:
|
|
||||||
- "8000:5010"
|
|
||||||
links:
|
|
||||||
- "db:database"
|
|
||||||
db:
|
|
||||||
image: postgres
|
|
||||||
|
|
||||||
networks:
|
|
||||||
front-tier:
|
|
||||||
back-tier:
|
|
||||||
admin:
|
|
||||||
volumes:
|
|
||||||
db-data:
|
|
|
@ -1,26 +0,0 @@
|
||||||
services:
|
|
||||||
frontend:
|
|
||||||
image: awesome/webapp
|
|
||||||
|
|
||||||
monitoring:
|
|
||||||
image: awesome/monitoring
|
|
||||||
depends_on:
|
|
||||||
- backend
|
|
||||||
volumes:
|
|
||||||
- type: volume
|
|
||||||
source: db-data
|
|
||||||
target: /data
|
|
||||||
volume:
|
|
||||||
nocopy: true
|
|
||||||
- type: bind
|
|
||||||
source: /var/run/postgres/postgres.sock
|
|
||||||
target: /var/run/postgres/postgres.sock
|
|
||||||
links:
|
|
||||||
- "db:database"
|
|
||||||
|
|
||||||
backend:
|
|
||||||
image: awesome/backend
|
|
||||||
db:
|
|
||||||
image: postgres
|
|
||||||
volumes:
|
|
||||||
db-data:
|
|
|
@ -1,44 +0,0 @@
|
||||||
services:
|
|
||||||
frontend:
|
|
||||||
image: awesome/webapp
|
|
||||||
networks:
|
|
||||||
- front-tier
|
|
||||||
- back-tier
|
|
||||||
|
|
||||||
monitoring:
|
|
||||||
image: awesome/monitoring
|
|
||||||
networks:
|
|
||||||
- admin
|
|
||||||
|
|
||||||
|
|
||||||
backend:
|
|
||||||
image: awesome/backend
|
|
||||||
networks:
|
|
||||||
back-tier:
|
|
||||||
aliases:
|
|
||||||
- database
|
|
||||||
admin:
|
|
||||||
aliases:
|
|
||||||
- mysql
|
|
||||||
volumes:
|
|
||||||
- type: volume
|
|
||||||
source: db-data
|
|
||||||
target: /data
|
|
||||||
volume:
|
|
||||||
nocopy: true
|
|
||||||
- type: bind
|
|
||||||
source: /var/run/postgres/postgres.sock
|
|
||||||
target: /var/run/postgres/postgres.sock
|
|
||||||
depends_on:
|
|
||||||
- monitoring
|
|
||||||
links:
|
|
||||||
- "db:database"
|
|
||||||
db:
|
|
||||||
image: postgres
|
|
||||||
|
|
||||||
networks:
|
|
||||||
front-tier:
|
|
||||||
back-tier:
|
|
||||||
admin:
|
|
||||||
volumes:
|
|
||||||
db-data:
|
|
|
@ -1,30 +0,0 @@
|
||||||
services:
|
|
||||||
frontend:
|
|
||||||
image: awesome/webapp
|
|
||||||
|
|
||||||
monitoring:
|
|
||||||
image: awesome/monitoring
|
|
||||||
|
|
||||||
|
|
||||||
backend:
|
|
||||||
image: awesome/backend
|
|
||||||
volumes:
|
|
||||||
- type: volume
|
|
||||||
source: db-data
|
|
||||||
target: /data
|
|
||||||
volume:
|
|
||||||
nocopy: true
|
|
||||||
- type: bind
|
|
||||||
source: /var/run/postgres/postgres.sock
|
|
||||||
target: /var/run/postgres/postgres.sock
|
|
||||||
depends_on:
|
|
||||||
- monitoring
|
|
||||||
extends:
|
|
||||||
service: frontend
|
|
||||||
links:
|
|
||||||
- "db:database"
|
|
||||||
db:
|
|
||||||
image: postgres
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
db-data:
|
|
|
@ -1,46 +0,0 @@
|
||||||
services:
|
|
||||||
frontend:
|
|
||||||
image: awesome/webapp
|
|
||||||
networks:
|
|
||||||
- front-tier
|
|
||||||
- back-tier
|
|
||||||
|
|
||||||
monitoring:
|
|
||||||
image: awesome/monitoring
|
|
||||||
networks:
|
|
||||||
- admin
|
|
||||||
|
|
||||||
|
|
||||||
backend:
|
|
||||||
image: awesome/backend
|
|
||||||
networks:
|
|
||||||
back-tier:
|
|
||||||
aliases:
|
|
||||||
- database
|
|
||||||
admin:
|
|
||||||
aliases:
|
|
||||||
- mysql
|
|
||||||
volumes:
|
|
||||||
- type: volume
|
|
||||||
source: db-data
|
|
||||||
target: /data
|
|
||||||
volume:
|
|
||||||
nocopy: true
|
|
||||||
- type: bind
|
|
||||||
source: /var/run/postgres/postgres.sock
|
|
||||||
target: /var/run/postgres/postgres.sock
|
|
||||||
depends_on:
|
|
||||||
- monitoring
|
|
||||||
extends:
|
|
||||||
service: frontend
|
|
||||||
links:
|
|
||||||
- "db:database"
|
|
||||||
db:
|
|
||||||
image: postgres
|
|
||||||
|
|
||||||
networks:
|
|
||||||
front-tier:
|
|
||||||
back-tier:
|
|
||||||
admin:
|
|
||||||
volumes:
|
|
||||||
db-data:
|
|
|
@ -1,30 +0,0 @@
|
||||||
services:
|
|
||||||
frontend:
|
|
||||||
image: awesome/webapp
|
|
||||||
|
|
||||||
monitoring:
|
|
||||||
image: awesome/monitoring
|
|
||||||
|
|
||||||
|
|
||||||
backend:
|
|
||||||
image: awesome/backend
|
|
||||||
volumes:
|
|
||||||
- type: volume
|
|
||||||
source: db-data
|
|
||||||
target: /data
|
|
||||||
volume:
|
|
||||||
nocopy: true
|
|
||||||
- type: bind
|
|
||||||
source: /var/run/postgres/postgres.sock
|
|
||||||
target: /var/run/postgres/postgres.sock
|
|
||||||
depends_on:
|
|
||||||
- monitoring
|
|
||||||
ports:
|
|
||||||
- "8000:5010"
|
|
||||||
links:
|
|
||||||
- "db:database"
|
|
||||||
db:
|
|
||||||
image: postgres
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
db-data:
|
|
|
@ -1,46 +0,0 @@
|
||||||
services:
|
|
||||||
frontend:
|
|
||||||
image: awesome/webapp
|
|
||||||
networks:
|
|
||||||
- front-tier
|
|
||||||
- back-tier
|
|
||||||
|
|
||||||
monitoring:
|
|
||||||
image: awesome/monitoring
|
|
||||||
networks:
|
|
||||||
- admin
|
|
||||||
|
|
||||||
|
|
||||||
backend:
|
|
||||||
image: awesome/backend
|
|
||||||
networks:
|
|
||||||
back-tier:
|
|
||||||
aliases:
|
|
||||||
- database
|
|
||||||
admin:
|
|
||||||
aliases:
|
|
||||||
- mysql
|
|
||||||
volumes:
|
|
||||||
- type: volume
|
|
||||||
source: db-data
|
|
||||||
target: /data
|
|
||||||
volume:
|
|
||||||
nocopy: true
|
|
||||||
- type: bind
|
|
||||||
source: /var/run/postgres/postgres.sock
|
|
||||||
target: /var/run/postgres/postgres.sock
|
|
||||||
depends_on:
|
|
||||||
- monitoring
|
|
||||||
ports:
|
|
||||||
- "8000:5010"
|
|
||||||
links:
|
|
||||||
- "db:database"
|
|
||||||
db:
|
|
||||||
image: postgres
|
|
||||||
|
|
||||||
networks:
|
|
||||||
front-tier:
|
|
||||||
back-tier:
|
|
||||||
admin:
|
|
||||||
volumes:
|
|
||||||
db-data:
|
|
|
@ -1,31 +0,0 @@
|
||||||
services:
|
|
||||||
frontend:
|
|
||||||
image: awesome/webapp
|
|
||||||
monitoring:
|
|
||||||
image: awesome/monitoring
|
|
||||||
|
|
||||||
|
|
||||||
backend:
|
|
||||||
image: awesome/backend
|
|
||||||
volumes:
|
|
||||||
- type: volume
|
|
||||||
source: db-data
|
|
||||||
target: /data
|
|
||||||
volume:
|
|
||||||
nocopy: true
|
|
||||||
- type: bind
|
|
||||||
source: /var/run/postgres/postgres.sock
|
|
||||||
target: /var/run/postgres/postgres.sock
|
|
||||||
depends_on:
|
|
||||||
- monitoring
|
|
||||||
extends:
|
|
||||||
service: frontend
|
|
||||||
ports:
|
|
||||||
- "8000:5010"
|
|
||||||
links:
|
|
||||||
- "db:database"
|
|
||||||
db:
|
|
||||||
image: postgres
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
db-data:
|
|
|
@ -1,48 +0,0 @@
|
||||||
services:
|
|
||||||
frontend:
|
|
||||||
image: awesome/webapp
|
|
||||||
networks:
|
|
||||||
- front-tier
|
|
||||||
- back-tier
|
|
||||||
|
|
||||||
monitoring:
|
|
||||||
image: awesome/monitoring
|
|
||||||
networks:
|
|
||||||
- admin
|
|
||||||
|
|
||||||
|
|
||||||
backend:
|
|
||||||
image: awesome/backend
|
|
||||||
networks:
|
|
||||||
back-tier:
|
|
||||||
aliases:
|
|
||||||
- database
|
|
||||||
admin:
|
|
||||||
aliases:
|
|
||||||
- mysql
|
|
||||||
volumes:
|
|
||||||
- type: volume
|
|
||||||
source: db-data
|
|
||||||
target: /data
|
|
||||||
volume:
|
|
||||||
nocopy: true
|
|
||||||
- type: bind
|
|
||||||
source: /var/run/postgres/postgres.sock
|
|
||||||
target: /var/run/postgres/postgres.sock
|
|
||||||
depends_on:
|
|
||||||
- monitoring
|
|
||||||
extends:
|
|
||||||
service: frontend
|
|
||||||
ports:
|
|
||||||
- "8000:5010"
|
|
||||||
links:
|
|
||||||
- "db:database"
|
|
||||||
db:
|
|
||||||
image: postgres
|
|
||||||
|
|
||||||
networks:
|
|
||||||
front-tier:
|
|
||||||
back-tier:
|
|
||||||
admin:
|
|
||||||
volumes:
|
|
||||||
db-data:
|
|
|
@ -1,13 +1,34 @@
|
||||||
from typer.testing import CliRunner
|
import os
|
||||||
from compose_viz import cli
|
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from typer.testing import CliRunner
|
||||||
|
|
||||||
|
from compose_viz import cli
|
||||||
|
|
||||||
runner = CliRunner()
|
runner = CliRunner()
|
||||||
|
|
||||||
|
|
||||||
def test_cli():
|
@pytest.mark.parametrize(
|
||||||
input_path = "tests/in/000001.yaml"
|
"test_file_path",
|
||||||
result = runner.invoke(cli.app, [input_path])
|
[
|
||||||
|
"tests/ymls/builds/docker-compose.yml",
|
||||||
|
"tests/ymls/depends_on/docker-compose.yml",
|
||||||
|
"tests/ymls/extends/docker-compose.yml",
|
||||||
|
"tests/ymls/links/docker-compose.yml",
|
||||||
|
"tests/ymls/networks/docker-compose.yml",
|
||||||
|
"tests/ymls/ports/docker-compose.yml",
|
||||||
|
"tests/ymls/volumes/docker-compose.yml",
|
||||||
|
"examples/full-stack-node-app/docker-compose.yml",
|
||||||
|
"examples/non-normative/docker-compose.yml",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_cli(test_file_path: str) -> None:
|
||||||
|
input_path = f"{test_file_path}"
|
||||||
|
output_path = "compose-viz-test.png"
|
||||||
|
result = runner.invoke(cli.app, ["-o", output_path, input_path])
|
||||||
|
|
||||||
assert result.exit_code == 0
|
assert result.exit_code == 0
|
||||||
assert f"Successfully parsed {input_path}\n" in result.stdout
|
assert f"Successfully parsed {input_path}\n" in result.stdout
|
||||||
|
assert os.path.exists(output_path)
|
||||||
|
|
||||||
|
os.remove(output_path)
|
||||||
|
|
28
tests/test_extends.py
Normal file
28
tests/test_extends.py
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from compose_viz.extends import Extends
|
||||||
|
|
||||||
|
|
||||||
|
def test_extend_init_normal() -> None:
|
||||||
|
try:
|
||||||
|
e = Extends(service_name="frontend", from_file="tests/ymls/others/empty.yaml")
|
||||||
|
|
||||||
|
assert e.service_name == "frontend"
|
||||||
|
assert e.from_file == "tests/ymls/others/empty.yaml"
|
||||||
|
except Exception as e:
|
||||||
|
assert False, e
|
||||||
|
|
||||||
|
|
||||||
|
def test_extend_init_without_from_file() -> None:
|
||||||
|
try:
|
||||||
|
e = Extends(service_name="frontend")
|
||||||
|
|
||||||
|
assert e.service_name == "frontend"
|
||||||
|
assert e.from_file is None
|
||||||
|
except Exception as e:
|
||||||
|
assert False, e
|
||||||
|
|
||||||
|
|
||||||
|
def test_extend_init_without_service_name() -> None:
|
||||||
|
with pytest.raises(TypeError):
|
||||||
|
Extends(from_file="tests/ymls/others/empty.yaml") # type: ignore
|
5
tests/test_module.py
Normal file
5
tests/test_module.py
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
|
def test_module():
|
||||||
|
assert os.system("python -m compose_viz") == 0
|
|
@ -1,28 +1,266 @@
|
||||||
from compose_viz.parser import Parser
|
import pytest
|
||||||
|
|
||||||
from compose_viz.compose import Compose
|
from compose_viz.compose import Compose
|
||||||
|
from compose_viz.extends import Extends
|
||||||
|
from compose_viz.parser import Parser
|
||||||
|
from compose_viz.port import Port, Protocol
|
||||||
from compose_viz.service import Service
|
from compose_viz.service import Service
|
||||||
|
from compose_viz.volume import Volume, VolumeType
|
||||||
|
|
||||||
|
|
||||||
def test_parse_file():
|
@pytest.mark.parametrize(
|
||||||
expected: Compose = Compose([
|
"test_file_path, expected",
|
||||||
Service(
|
[
|
||||||
name='frontend',
|
(
|
||||||
image='awesome/webapp',
|
"builds/docker-compose",
|
||||||
networks=['front-tier', 'back-tier'],
|
Compose(
|
||||||
|
services=[
|
||||||
|
Service(
|
||||||
|
name="frontend",
|
||||||
|
image="build from './frontend', image: awesome/frontend",
|
||||||
|
),
|
||||||
|
Service(
|
||||||
|
name="backend",
|
||||||
|
image="build from 'backend' using '../backend.Dockerfile'",
|
||||||
|
),
|
||||||
|
Service(
|
||||||
|
name="db",
|
||||||
|
image="build from './db'",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
Service(
|
(
|
||||||
name='monitoring',
|
"depends_on/docker-compose",
|
||||||
image='awesome/monitoring',
|
Compose(
|
||||||
networks=['admin'],
|
services=[
|
||||||
|
Service(
|
||||||
|
name="frontend",
|
||||||
|
image="awesome/frontend",
|
||||||
|
depends_on=[
|
||||||
|
"db",
|
||||||
|
"redis",
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Service(
|
||||||
|
name="backend",
|
||||||
|
image="awesome/backend",
|
||||||
|
depends_on=[
|
||||||
|
"db",
|
||||||
|
"redis",
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Service(
|
||||||
|
name="db",
|
||||||
|
image="mysql",
|
||||||
|
),
|
||||||
|
Service(
|
||||||
|
name="redis",
|
||||||
|
image="redis",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
Service(
|
(
|
||||||
name='backend',
|
"extends/docker-compose",
|
||||||
image='awesome/backend',
|
Compose(
|
||||||
networks=['back-tier', 'admin'],
|
services=[
|
||||||
|
Service(
|
||||||
|
name="base",
|
||||||
|
image="alpine:latest",
|
||||||
|
),
|
||||||
|
Service(
|
||||||
|
name="derive_from_base",
|
||||||
|
image="alpine:edge",
|
||||||
|
extends=Extends(
|
||||||
|
service_name="base",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Service(
|
||||||
|
name="derive_from_file",
|
||||||
|
extends=Extends(
|
||||||
|
service_name="web",
|
||||||
|
from_file="web.yml",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
])
|
(
|
||||||
|
"links/docker-compose",
|
||||||
|
Compose(
|
||||||
|
services=[
|
||||||
|
Service(
|
||||||
|
name="frontend",
|
||||||
|
image="awesome/frontend",
|
||||||
|
links=[
|
||||||
|
"db:database",
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Service(
|
||||||
|
name="db",
|
||||||
|
image="mysql",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"networks/docker-compose",
|
||||||
|
Compose(
|
||||||
|
services=[
|
||||||
|
Service(
|
||||||
|
name="frontend",
|
||||||
|
image="awesome/frontend",
|
||||||
|
networks=[
|
||||||
|
"front-tier",
|
||||||
|
"back-tier",
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Service(
|
||||||
|
name="monitoring",
|
||||||
|
image="awesome/monitoring",
|
||||||
|
networks=[
|
||||||
|
"admin",
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Service(
|
||||||
|
name="backend",
|
||||||
|
image="awesome/backend",
|
||||||
|
networks=[
|
||||||
|
"back-tier",
|
||||||
|
"admin",
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"ports/docker-compose",
|
||||||
|
Compose(
|
||||||
|
services=[
|
||||||
|
Service(
|
||||||
|
name="frontend",
|
||||||
|
image="awesome/frontend",
|
||||||
|
ports=[
|
||||||
|
Port(
|
||||||
|
host_port="0.0.0.0:3000",
|
||||||
|
container_port="3000",
|
||||||
|
),
|
||||||
|
Port(
|
||||||
|
host_port="0.0.0.0:3000-3005",
|
||||||
|
container_port="3000-3005",
|
||||||
|
),
|
||||||
|
Port(
|
||||||
|
host_port="0.0.0.0:9090-9091",
|
||||||
|
container_port="8080-8081",
|
||||||
|
),
|
||||||
|
Port(
|
||||||
|
host_port="0.0.0.0:49100",
|
||||||
|
container_port="22",
|
||||||
|
),
|
||||||
|
Port(
|
||||||
|
host_port="127.0.0.1:8001",
|
||||||
|
container_port="8001",
|
||||||
|
),
|
||||||
|
Port(
|
||||||
|
host_port="127.0.0.1:5000-5010",
|
||||||
|
container_port="5000-5010",
|
||||||
|
),
|
||||||
|
Port(
|
||||||
|
host_port="0.0.0.0:6060",
|
||||||
|
container_port="6060",
|
||||||
|
protocol=Protocol.udp,
|
||||||
|
),
|
||||||
|
Port(
|
||||||
|
host_port="127.0.0.1:8080",
|
||||||
|
container_port="80",
|
||||||
|
protocol=Protocol.tcp,
|
||||||
|
),
|
||||||
|
Port(
|
||||||
|
host_port="0.0.0.0:443",
|
||||||
|
container_port="443",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"volumes/docker-compose",
|
||||||
|
Compose(
|
||||||
|
services=[
|
||||||
|
Service(
|
||||||
|
name="backend",
|
||||||
|
image="awesome/backend",
|
||||||
|
volumes=[
|
||||||
|
Volume(
|
||||||
|
source="./data",
|
||||||
|
target="/data",
|
||||||
|
),
|
||||||
|
Volume(
|
||||||
|
source="/var/run/postgres/postgres.sock",
|
||||||
|
target="/var/run/postgres/postgres.sock",
|
||||||
|
type=VolumeType.bind,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Service(
|
||||||
|
name="common",
|
||||||
|
image="busybox",
|
||||||
|
volumes=[
|
||||||
|
Volume(
|
||||||
|
source="common-volume",
|
||||||
|
target="/var/lib/backup/data",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Service(
|
||||||
|
name="cli",
|
||||||
|
extends=Extends(
|
||||||
|
service_name="common",
|
||||||
|
),
|
||||||
|
volumes=[
|
||||||
|
Volume(
|
||||||
|
source="cli-volume",
|
||||||
|
target="/var/lib/backup/data",
|
||||||
|
access_mode="ro,z",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_parse_file(test_file_path: str, expected: Compose) -> None:
|
||||||
parser = Parser()
|
parser = Parser()
|
||||||
actual = parser.parse('tests/in/000001.yaml')
|
actual = parser.parse(f"tests/ymls/{test_file_path}.yml")
|
||||||
|
|
||||||
assert actual == expected
|
assert len(actual.services) == len(expected.services)
|
||||||
|
|
||||||
|
for actual_service, expected_service in zip(actual.services, expected.services):
|
||||||
|
assert actual_service.name == expected_service.name
|
||||||
|
assert actual_service.image == expected_service.image
|
||||||
|
|
||||||
|
assert len(actual_service.ports) == len(expected_service.ports)
|
||||||
|
for actual_port, expected_port in zip(actual_service.ports, expected_service.ports):
|
||||||
|
assert actual_port.host_port == expected_port.host_port
|
||||||
|
assert actual_port.container_port == expected_port.container_port
|
||||||
|
assert actual_port.protocol == expected_port.protocol
|
||||||
|
|
||||||
|
assert actual_service.networks == expected_service.networks
|
||||||
|
|
||||||
|
assert len(actual_service.volumes) == len(expected_service.volumes)
|
||||||
|
for actual_volume, expected_volume in zip(actual_service.volumes, expected_service.volumes):
|
||||||
|
assert actual_volume.source == expected_volume.source
|
||||||
|
assert actual_volume.target == expected_volume.target
|
||||||
|
assert actual_volume.type == expected_volume.type
|
||||||
|
|
||||||
|
assert actual_service.depends_on == expected_service.depends_on
|
||||||
|
assert actual_service.links == expected_service.links
|
||||||
|
|
||||||
|
assert (actual_service.extends is not None) == (expected_service.extends is not None)
|
||||||
|
|
||||||
|
if (actual_service.extends is not None) and (expected_service.extends is not None):
|
||||||
|
assert actual_service.extends.service_name == expected_service.extends.service_name
|
||||||
|
assert actual_service.extends.from_file == expected_service.extends.from_file
|
||||||
|
|
18
tests/test_parser.py
Normal file
18
tests/test_parser.py
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from compose_viz.parser import Parser
|
||||||
|
|
||||||
|
|
||||||
|
def test_parser_error_parsing_file() -> None:
|
||||||
|
with pytest.raises(RuntimeError, match=r"Error parsing file 'tests/ymls/others/invalid.yml'.*"):
|
||||||
|
Parser().parse("tests/ymls/others/invalid.yml")
|
||||||
|
|
||||||
|
|
||||||
|
def test_parser_invalid_yaml() -> None:
|
||||||
|
with pytest.raises(RuntimeError, match=r"Empty yaml file, aborting."):
|
||||||
|
Parser().parse("tests/ymls/others/empty.yml")
|
||||||
|
|
||||||
|
|
||||||
|
def test_parser_no_services_found() -> None:
|
||||||
|
with pytest.raises(RuntimeError, match=r"No services found, aborting."):
|
||||||
|
Parser().parse("tests/ymls/others/no-services.yml")
|
23
tests/test_port.py
Normal file
23
tests/test_port.py
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
from compose_viz.port import Port, Protocol
|
||||||
|
|
||||||
|
|
||||||
|
def test_port_init_normal() -> None:
|
||||||
|
try:
|
||||||
|
p = Port(host_port="8080", container_port="80")
|
||||||
|
|
||||||
|
assert p.host_port == "8080"
|
||||||
|
assert p.container_port == "80"
|
||||||
|
assert p.protocol == Protocol.any
|
||||||
|
except Exception as e:
|
||||||
|
assert False, e
|
||||||
|
|
||||||
|
|
||||||
|
def test_port_with_protocol() -> None:
|
||||||
|
try:
|
||||||
|
p = Port(host_port="8080", container_port="80", protocol=Protocol.udp)
|
||||||
|
|
||||||
|
assert p.host_port == "8080"
|
||||||
|
assert p.container_port == "80"
|
||||||
|
assert p.protocol == Protocol.udp
|
||||||
|
except Exception as e:
|
||||||
|
assert False, e
|
|
@ -1,11 +1,11 @@
|
||||||
from typer.testing import CliRunner
|
from typer.testing import CliRunner
|
||||||
from compose_viz import cli, __app_name__, __version__
|
|
||||||
|
|
||||||
|
from compose_viz import __app_name__, __version__, cli
|
||||||
|
|
||||||
runner = CliRunner()
|
runner = CliRunner()
|
||||||
|
|
||||||
|
|
||||||
def test_version():
|
def test_version() -> None:
|
||||||
result = runner.invoke(cli.app, ["--version"])
|
result = runner.invoke(cli.app, ["--version"])
|
||||||
|
|
||||||
assert result.exit_code == 0
|
assert result.exit_code == 0
|
||||||
|
|
37
tests/test_volume.py
Normal file
37
tests/test_volume.py
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
from compose_viz.volume import Volume, VolumeType
|
||||||
|
|
||||||
|
|
||||||
|
def test_volume_init_normal() -> None:
|
||||||
|
try:
|
||||||
|
v = Volume(source="./foo", target="./bar")
|
||||||
|
|
||||||
|
assert v.source == "./foo"
|
||||||
|
assert v.target == "./bar"
|
||||||
|
assert v.type == VolumeType.volume
|
||||||
|
assert v.access_mode == "rw"
|
||||||
|
except Exception as e:
|
||||||
|
assert False, e
|
||||||
|
|
||||||
|
|
||||||
|
def test_volume_with_type() -> None:
|
||||||
|
try:
|
||||||
|
v = Volume(source="./foo", target="./bar", type=VolumeType.bind)
|
||||||
|
|
||||||
|
assert v.source == "./foo"
|
||||||
|
assert v.target == "./bar"
|
||||||
|
assert v.type == VolumeType.bind
|
||||||
|
assert v.access_mode == "rw"
|
||||||
|
except Exception as e:
|
||||||
|
assert False, e
|
||||||
|
|
||||||
|
|
||||||
|
def test_volume_with_access_mode() -> None:
|
||||||
|
try:
|
||||||
|
v = Volume(source="./foo", target="./bar", access_mode="ro,z")
|
||||||
|
|
||||||
|
assert v.source == "./foo"
|
||||||
|
assert v.target == "./bar"
|
||||||
|
assert v.type == VolumeType.volume
|
||||||
|
assert v.access_mode == "ro,z"
|
||||||
|
except Exception as e:
|
||||||
|
assert False, e
|
15
tests/ymls/builds/docker-compose.yml
Normal file
15
tests/ymls/builds/docker-compose.yml
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
version: "3.9"
|
||||||
|
|
||||||
|
services:
|
||||||
|
frontend:
|
||||||
|
image: awesome/frontend
|
||||||
|
build: ./frontend
|
||||||
|
|
||||||
|
backend:
|
||||||
|
build:
|
||||||
|
context: backend
|
||||||
|
dockerfile: ../backend.Dockerfile
|
||||||
|
|
||||||
|
db:
|
||||||
|
build:
|
||||||
|
context: ./db
|
19
tests/ymls/depends_on/docker-compose.yml
Normal file
19
tests/ymls/depends_on/docker-compose.yml
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
version: "3.9"
|
||||||
|
|
||||||
|
services:
|
||||||
|
frontend:
|
||||||
|
image: awesome/frontend
|
||||||
|
depends_on:
|
||||||
|
db:
|
||||||
|
condition: service_healthy
|
||||||
|
redis:
|
||||||
|
condition: service_started
|
||||||
|
backend:
|
||||||
|
image: awesome/backend
|
||||||
|
depends_on:
|
||||||
|
- db
|
||||||
|
- redis
|
||||||
|
db:
|
||||||
|
image: mysql
|
||||||
|
redis:
|
||||||
|
image: redis
|
14
tests/ymls/extends/docker-compose.yml
Normal file
14
tests/ymls/extends/docker-compose.yml
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
version: "3.9"
|
||||||
|
|
||||||
|
services:
|
||||||
|
base:
|
||||||
|
image: alpine:latest
|
||||||
|
tty: true
|
||||||
|
derive_from_base:
|
||||||
|
image: alpine:edge
|
||||||
|
extends:
|
||||||
|
service: base
|
||||||
|
derive_from_file:
|
||||||
|
extends:
|
||||||
|
file: web.yml
|
||||||
|
service: web
|
5
tests/ymls/extends/web.yml
Normal file
5
tests/ymls/extends/web.yml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
version: "3.9"
|
||||||
|
|
||||||
|
services:
|
||||||
|
web:
|
||||||
|
image: awesome/web
|
|
@ -1,9 +1,9 @@
|
||||||
version: "3.9"
|
version: "3.9"
|
||||||
services:
|
|
||||||
|
|
||||||
web:
|
services:
|
||||||
build: .
|
frontend:
|
||||||
|
image: awesome/frontend
|
||||||
links:
|
links:
|
||||||
- "db:database"
|
- "db:database"
|
||||||
db:
|
db:
|
||||||
image: postgres
|
image: mysql
|
|
@ -1,6 +1,8 @@
|
||||||
|
version: "3.9"
|
||||||
|
|
||||||
services:
|
services:
|
||||||
frontend:
|
frontend:
|
||||||
image: awesome/webapp
|
image: awesome/frontend
|
||||||
networks:
|
networks:
|
||||||
- front-tier
|
- front-tier
|
||||||
- back-tier
|
- back-tier
|
||||||
|
@ -23,4 +25,4 @@ services:
|
||||||
networks:
|
networks:
|
||||||
front-tier:
|
front-tier:
|
||||||
back-tier:
|
back-tier:
|
||||||
admin:
|
admin:
|
0
tests/ymls/others/empty.yml
Normal file
0
tests/ymls/others/empty.yml
Normal file
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue