Skip to content

Commit

Permalink
feat(Docker): create container image for every release
Browse files Browse the repository at this point in the history
  • Loading branch information
BjoernLudwigPTB committed Jul 21, 2021
2 parents 0a2ada9 + 2ef8351 commit 1a40eaf
Show file tree
Hide file tree
Showing 10 changed files with 443 additions and 52 deletions.
153 changes: 153 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@ executors:
working_directory: ~/repo
docker:
- image: circleci/python:3.8
builder:
working_directory: ~/repo
docker:
- image: circleci/python:3.9
image_dealer:
working_directory: ~/repo
docker:
- image: circleci/buildpack-deps:focal

workflows:
# Create workflow for testing and deploying agentMET4FOF.
Expand All @@ -36,6 +44,7 @@ workflows:
type: approval
requires:
- preview_release
- test_image
filters:
branches:
# This assures the job only being triggered on branch master.
Expand All @@ -50,6 +59,20 @@ workflows:
- GitHub pushes to BjoernLudwigPTB's public_repos
requires:
- confirm_previewed_release_actions
- build_image:
context:
- Docker publishing for agents
- test_image:
context:
- Docker publishing for agents
requires:
- build_image
- retag_and_deploy_image:
context:
- Docker publishing for agents
- CircleCI agentMET4FOF docker publishing
requires:
- release

commands:
# Reusable command to prepare the environment for testing.
Expand Down Expand Up @@ -305,3 +328,133 @@ jobs:
python-semantic-release would perform the following actions:
"
semantic-release --noop publish
build_image:
executor: builder
working_directory: ~/repo
steps:
- checkout

- setup_remote_docker

- run:
name: Install repo2docker
command: |
python3 -m pip install chardet jupyter-repo2docker
- run:
name: Build image
command: |
jupyter-repo2docker --no-run --image-name ${IMAGE_NAME}:latest .
- run:
name: Save Docker image
command: |
docker save ${IMAGE_NAME}:latest | \
gzip > docker_image_agentMET4FOF_jupyter.tar.gz
# Permanently store the built image to test and potentially deploy it.
- persist_to_workspace:
root: .
paths:
- ./docker_image_agentMET4FOF_jupyter.tar.gz

- store_artifacts:
path: ./docker_image_agentMET4FOF_jupyter.tar.gz

test_image:
executor: image_dealer
working_directory: ~/repo
steps:
- attach_workspace:
at: /tmp/workspace

- setup_remote_docker

- run:
name: Retrieve built and stored image for testing
command: |
docker load -i /tmp/workspace/docker_image_agentMET4FOF_jupyter.tar.gz
- run:
name: Test image's notebook server
command: |
docker run --name agents --publish 127.0.0.1:8888:8888 \
-d --rm ${IMAGE_NAME}:latest
docker run --network container:agents \
appropriate/curl --retry 10 --retry-delay 1 \
--retry-connrefused http://127.0.0.1:8888
docker stop agents
- run:
name: Test image's dashboard
command: |
docker run --name agents --publish 127.0.0.1:8050:8050 --rm -d \
${IMAGE_NAME}:latest python \
${HOME}/agentMET4FOF_tutorials/tutorial_1_generator_agent.py
docker run --network container:agents \
appropriate/curl --retry 10 --retry-delay 1 \
--retry-connrefused http://127.0.0.1:8050
docker stop agents
- run:
name: Test image's dashboard in a subfolder
command: |
subfolder_name=dashboard_subfolder
docker run --name agents --publish 127.0.0.1:8050:8050 --rm -d \
--env DASH_URL_BASE_PATHNAME=/$subfolder_name/ \
${IMAGE_NAME}:latest python \
${HOME}/agentMET4FOF_tutorials/tutorial_1_generator_agent.py
docker run --network container:agents \
appropriate/curl --retry 10 --retry-delay 1 \
--retry-connrefused http://127.0.0.1:8050/$subfolder_name/
retag_and_deploy_image:
executor: image_dealer
working_directory: ~/repo
steps:
- attach_workspace:
at: /tmp/workspace

- setup_remote_docker

- run:
name: Retrieve built and tested image
command: |
docker load -i /tmp/workspace/docker_image_agentMET4FOF_jupyter.tar.gz
- run:
name: Retag image with corresponding version number and store new archive
command: |
version=$(docker run --rm ${IMAGE_NAME}:latest \
awk -F '"' '/__version/{print $(NF-1)}' agentMET4FOF/__init__.py)
docker tag ${IMAGE_NAME} ${ORG_NAME}/${IMAGE_NAME}:$version
docker save ${ORG_NAME}/${IMAGE_NAME}:$version | \
gzip > tagged_docker_image_agentMET4FOF_jupyter.tar.gz
- run:
name: Install the GitHub cli 'gh'
command: |
curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg |\
sudo gpg --dearmor -o /usr/share/keyrings/githubcli-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) \
signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] \
https://cli.github.com/packages stable main" | \
sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null
sudo apt-get update
sudo apt-get install gh
- run:
name: Upload current image
command: |
most_current_release=$(
git -c 'versionsort.suffix=-' ls-remote \
--exit-code --refs --sort='version:refname' --tags \
https://github.com/${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}.git \
'*.*.*' | tail --lines=1 | cut --delimiter='/' --fields=3
)
gh release upload --repo \
${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME} \
$most_current_release \
tagged_docker_image_agentMET4FOF_jupyter.tar.gz#"Docker \
image for agentMET4FOF Jupyter Notebook server"
76 changes: 48 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
<p align="center">
<!-- CircleCI Tests -->
<a href="https://circleci.com/gh/Met4FoF/agentMET4FOF"><img alt="CircleCI pipeline status badge" src="https://circleci.com/gh/Met4FoF/agentMET4FOF.svg?style=shield"></a>
<a href="https://circleci.com/gh/Met4FoF/agentMET4FOF"><img alt="CircleCI pipeline
status badge" src="https://circleci.com/gh/Met4FoF/agentMET4FOF.svg?
style=shield"></a>
<!-- ReadTheDocs Documentation -->
<a href="https://agentmet4fof.readthedocs.io/">
<img src="https://readthedocs.org/projects/agentmet4fof/badge/?version=latest" alt="ReadTheDocs badge">
</a>
<!-- CodeCov(erage) -->
<a href="https://codecov.io/gh/Met4FoF/agentMET4FOF">
<img src="https://codecov.io/gh/Met4FoF/agentMET4FOF/branch/master/graph/badge.svg?token=ofAPdSudLy"/>
<img src="https://codecov.io/gh/Met4FoF/agentMET4FOF/branch/master/graph/badge.svg?token=ofAPdSudLy" alt="CodeCov badge"/>
</a>
<!-- PyPI Version -->
<a href="https://pypi.org/project/agentmet4fof">
<img src="https://img.shields.io/pypi/v/agentmet4fof.svg?label=release&color=blue&style=flat-square" alt="pypi">
</a>
<!-- PyPI License -->
<a href="https://www.gnu.org/licenses/lgpl-3.0.en.html">
<img alt="PyPI - license badge" src="https://img.shields.io/pypi/l/agentMET4FOF?color=bright">
<img alt="PyPI - license badge"
src="https://img.shields.io/pypi/l/agentMET4FOF?color=bright">
</a>
<!-- Zenodo DOI -->
<a href="https://doi.org/10.5281/zenodo.4560343">
Expand All @@ -28,7 +31,7 @@
agentMET4FOF is an implementation of a multi-agent system for agent-based
analysis and processing of both static data sets and data streams with IIoT
applications in mind. More on the motivation that drives the project can be found
in the section <a href="#about">About</a>.
in the section <!--suppress HtmlUnknownAnchorTarget --><a href="#about">About</a>.
</p>

## Table of content
Expand Down Expand Up @@ -111,13 +114,14 @@ One of the many questions that drive us in the project is:
Some notable features of agentMET4FOF include :

- Modular agent classes for metrological data streams and analytics
- A built-in buffering mechanism to decouple transmission, processing and visualization of data
- A built-in buffering mechanism to decouple transmission, processing and visualization
of data
- Easy connection among software agents to send and receive data
- Choose backends between:
- [_Osbrain_](https://osbrain.readthedocs.io/en/stable/) for simulating as well as handling real distributed
systems running Python connected via a TCP network, and
- [_Mesa_](https://mesa.readthedocs.io/en/stable/) for local simulations of distributed systems, debugging and
more high-performance execution
- [_Osbrain_](https://osbrain.readthedocs.io/en/stable/) for simulating as well as
handling real distributed systems running Python connected via a TCP network, and
- [_Mesa_](https://mesa.readthedocs.io/en/stable/) for local simulations of
distributed systems, debugging and more high-performance execution
- Interactive and customisable dashboard from the get-go to:
- Visualize and change agent-network topologies
- Visualize groups of cooperative agents as _Coalitions_
Expand All @@ -134,9 +138,10 @@ more pre-made agents to your network all during run-time. The address to your
dashboard is printed to the console on every launch of an agent network.

The following image is close to what you will find in your browser on execution of
tutorial 2. For details on the tutorials visit our [video tutorial series](#video-tutorial-series).
tutorial 2. For details on the tutorials visit our
[video tutorial series](#video-tutorial-series).

![Web Screenshot](https://raw.githubusercontent.com/Met4FoF/agentMET4FOF/develop/docs/screenshot_met4fof.png)
![](https://raw.githubusercontent.com/Met4FoF/agentMET4FOF/develop/docs/screenshot_met4fof.png)

## 📖Documentation and video tutorials

Expand All @@ -145,7 +150,9 @@ Extended

### Video tutorial series

Additionally, we provide some [video tutorials based on agentMET4FOF 0.4.1 on the project homepage](https://www.ptb.de/empir2018/met4fof/information-communication/video-portal/)
Additionally, we provide some
[video tutorials based on agentMET4FOF 0.4.1 on the project homepage
](https://www.ptb.de/empir2018/met4fof/information-communication/video-portal/)
in the section _Tutorials for the multi-agent system agentMET4FOF_.
You can self-register on the linked page and get started immediately. The video series
begins with our motivation for creating agentMET4FOF, guide you through the
Expand All @@ -158,21 +165,31 @@ In an early development stage we held a live online tutorial based on
[agentMET4FOF 0.1.0](https://github.com/Met4FoF/agentMET4FOF/releases/0.1.0/)
which you can [download](https://github.com/Met4FoF/agentMET4FOF/releases/download/0.1.0/Met4FoF.MAS.webinar.mp4).

If questions arise, or you feel something is missing, reach out to [us](https://github.com/Met4FoF/agentMET4FOF/graphs/contributors).
If questions arise, or you feel something is missing, reach out to
[us](https://github.com/Met4FoF/agentMET4FOF/graphs/contributors).

## 💻Installation

The installation of agentMET4FOF is as straightforward as the Python
ecosystem suggests. In the [video tutorials series](#video-tutorial-series)
we guide you through every step until you have agentMET4FOF running on
your machine. Besides that we have more details in the [installation
There are different ways to run agentMET4FOF. Either:

1. you [install Python](https://www.python.org/downloads/) and our package
[agentMET4FOF](https://pypi.org/project/agentMET4FOF/) in a virtual Python
environment on your computer, or
2. you [install Docker](https://docs.docker.com/get-docker/), [start agentMET4FOF in
a container](https://agentmet4fof.readthedocs.io/en/latest/INSTALL.html#start-a-container-from-the-image)
and [visit the Jupyter Notebook server and the agentMET4FOF dashboard directly in
your browser](https://agentmet4fof.readthedocs.io/en/latest/INSTALL.html#start-a-container-from-the-image-for-local-use)
or even [deploy it over a proper webserver](https://agentmet4fof.readthedocs.io/en/latest/INSTALL.html#deploy-the-containerized-agents-via-a-webserver).

In the [video tutorials series](#video-tutorial-series)
we guide you through every step of option 1. More detailed instructions on both
options you can find in the [installation
section of the docs](https://agentmet4fof.readthedocs.io/en/latest/INSTALL.html).

## 💨Coming soon

- Dockerize agentMET4FOF
- Improve handling of metadata
- Further improve plotting
- Improved handling of metadata
- More advanced signal processing

For a comprehensive overview of current development activities and upcoming tasks,
take a look at the [project board](https://github.com/Met4FoF/agentMET4FOF/projects/1),
Expand All @@ -182,20 +199,23 @@ take a look at the [project board](https://github.com/Met4FoF/agentMET4FOF/proje
## 🖋Citation

If you publish results obtained with the help of agentMET4FOF, please cite the linked
[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.4560344.svg)](https://doi.org/10.5281/zenodo.4560344).
[![](https://zenodo.org/badge/DOI/10.5281/zenodo.4560344.svg)
](https://doi.org/10.5281/zenodo.4560344).

## 💎Acknowledgement

This work was part of the Joint Research Project [Metrology for the Factory of the Future (Met4FoF), project number 17IND12](https://www.ptb.de/empir2018/met4fof/home/)
of the European Metrology Programme for Innovation and Research (EMPIR). The [EMPIR](http://msu.euramet.org)
is jointly funded by the EMPIR participating countries within EURAMET and the European
Union.
This work was part of the Joint Research Project [Metrology for the Factory of the
Future (Met4FoF), project number 17IND12](https://www.ptb.de/empir2018/met4fof/home/)
of the European Metrology Programme for Innovation and Research (EMPIR). The
[EMPIR](http://msu.euramet.org) is jointly funded by the EMPIR participating
countries within EURAMET and the European Union.

## ⚠Disclaimer

This software is developed as a joint effort of several project partners namely:

- [Institute for Manufacturing of the University of Cambridge (IfM)](https://www.ifm.eng.cam.ac.uk/)
- [Institute for Manufacturing of the University of Cambridge (IfM)
](https://www.ifm.eng.cam.ac.uk/)
- [Physikalisch-Technische Bundesanstalt (PTB)](https://www.ptb.de/)
- [Van Swinden Laboratory (VSL)](https://www.vsl.nl/en/)
- [National Physics Laboratory (NPL)](https://www.npl.co.uk/)
Expand All @@ -209,5 +229,5 @@ connection with the use of this software.

## ©License

agentMET4FOF is distributed under the [LGPLv3 license](https://github.com/Met4FoF/agentMET4FOF/blob/develop/license.md).

agentMET4FOF is distributed under the
[LGPLv3 license](https://github.com/Met4FoF/agentMET4FOF/blob/develop/license.md).
36 changes: 26 additions & 10 deletions agentMET4FOF/dashboard/Dashboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class AgentDashboard:
An internal _Dashboard_Control object is instantiated inside this object, which manages access to the AgentNetwork.
"""
def __init__(self, dashboard_modules=[], dashboard_layouts=[],
dashboard_update_interval = 3, max_monitors=10, ip_addr="127.0.0.1",
dashboard_update_interval = 3, max_monitors=10, ip_addr="0.0.0.0",
port=8050, agentNetwork="127.0.0.1", agent_ip_addr=3333,
agent_port=None, network_stylesheet=[], hide_default_edge=True, **kwargs):
"""
Expand Down Expand Up @@ -77,17 +77,33 @@ def __init__(self, dashboard_modules=[], dashboard_layouts=[],
def run(self):
"""This is actually executed on calling start() and brings up the server"""
if hasattr(self, "_server"):
print(
f"\n--------------------------------------------------------------\n"
f"| |\n"
f"| Your agent network is starting up. Open your browser and |\n"
f"| visit the agentMET4FOF dashboard on "
f"http://{self.ip_addr}:{self.port}/ |\n"
f"| |\n"
f"--------------------------------------------------------------\n"
)
self._show_startup_message()
self._server.serve_forever()

def _show_startup_message(self):
"""This method prints the startup message of the webserver/dashboard"""
crucial_line = (
f"\n| visit the agentMET4FOF dashboard on http:/"
f"/{self.ip_addr}:{self.port}/ |"
)
crucial_line_len = len(crucial_line)

print(
f"\n|-".ljust(crucial_line_len - 1, "-"),
"|\n|".ljust(crucial_line_len, " "),
"|\n"
f"| Your agent network is starting up. Open your browser and".ljust(
crucial_line_len, " "
),
"|",
crucial_line,
"\n|".ljust(crucial_line_len - 1, " "),
f"|"
f"\n|-".ljust(crucial_line_len, "-"),
"|\n",
sep="",
)

def init_app_layout(self,update_interval_seconds=3, max_monitors=10,
dashboard_layouts=[],
network_stylesheet=[], hide_default_edge=True, **kwargs):
Expand Down
Loading

0 comments on commit 1a40eaf

Please sign in to comment.