Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
name: Docker Hub

on:
push:
tags:
- 'v[0-9]+.[0-9]+.[0-9]+'
- '!v[0-9]+.[0-9]+.[0-9]+[ab][0-9]+'

env:
IMAGE_NAME: csdms/bmi-example-c-grpc4bmi

jobs:

build-and-push:
runs-on: ubuntu-latest

steps:
- name: Get version
id: vars
run: echo "version=${GITHUB_REF:11}" >> $GITHUB_OUTPUT

- name: Checkout
uses: actions/checkout@v4

- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

- name: Set up Docker buildx
uses: docker/setup-buildx-action@v3
with:
platforms: linux/amd64,linux/arm64

- name: Build and push
uses: docker/build-push-action@v6
with:
platforms: linux/amd64,linux/arm64
context: images/conda-base
push: true
tags: ${{ env.IMAGE_NAME }}:latest,${{ env.IMAGE_NAME }}:${{ steps.vars.outputs.version }}
49 changes: 49 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: Test

on:
push:
pull_request:
schedule:
- cron: '07 4 3 * *' # 4:07a on third day of the month

concurrency:
group: ${{ github.ref }}-${{ github.workflow }}
cancel-in-progress: true

jobs:

test:
name: Run tests
if:
github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository

runs-on: ${{ matrix.os }}

defaults:
run:
shell: bash -l {0}

strategy:
matrix:
os: [ubuntu-latest]
python-version: ["3.13"]

steps:
- uses: actions/checkout@v4

- name: Install Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Install requirements
run: pip install pytest nbmake -r examples/requirements.txt

- name: Check example script
working-directory: ${{ github.workspace }}/examples
run: |
python run-model-through-grpc4bmi.py

- name: Check example notebook
run: |
pytest examples --nbmake --nbmake-timeout=3000 -v
51 changes: 43 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,45 @@

Set up a [grpc4bmi](https://grpc4bmi.readthedocs.io) server
to run a containerized version
of the [Basic Model Interface](https://bmi.readthedocs.io)
of the [Basic Model Interface](https://bmi.readthedocs.io) (BMI)
[C example](https://github.com/csdms/bmi-example-c)
through Python.

## Build

There are two options for building this project:

1. from a base image, [source-base](./images/source-base/), where grpc and its dependent libraries, grpc4bmi, and the BMI C example are all built from source
1. from a base image, [conda-base](./images/conda-base/), where grpc and its dependent libraries are installed through conda-forge, the BMI C example is installed from a separate conda-based Docker image, and grpc4bmi is built from source

In each case, the grpc4bmi server is exposed through port 55555.

### source-base

Build this example locally with:
```
docker build --tag bmi-example-c-grpc4bmi .
docker build --tag bmi-example-c-grpc4bmi images/source-base
```
The image is built on the [mdpiper/grpc4bmi-154](https://hub.docker.com/r/mdpiper/grpc4bmi-154) base image.
The image is (temporarily) built on the [mdpiper/grpc4bmi](https://hub.docker.com/r/mdpiper/grpc4bmi) base image.
The OS is Linux/Ubuntu.
The C BMI example, grpc4bmi, and the grpc4bmi server are installed in `/usr/local`.
The server is exposed through port 55555.

### conda-base

Build this example locally with:
```
docker build --tag bmi-example-c-grpc4bmi images/conda-base
```
The image is built on the [csdms/grpc4bmi](https://hub.docker.com/r/csdms/grpc4bmi) base image,
which is built on the [condaforge/miniforge3](https://hub.docker.com/r/condaforge/miniforge3) base image.
The OS is Linux/Ubuntu.
The C BMI example, grpc4bmi, and the grpc4bmi server are installed in `/opt/conda`.

## Run

Use the grpc4bmi [Docker client](https://grpc4bmi.readthedocs.io/en/latest/container/usage.html#docker)
to access the BMI methods of the containerized model.
Use the grpc4bmi Docker client to access the BMI methods of the containerized model.

Install grpc4bmi with *pip*:
Install with *pip*:
```
pip install grpc4bmi
```
Expand All @@ -38,11 +56,28 @@ del m # stop container cleanly
```

If the image isn't found locally, it's pulled from Docker Hub
(e.g., try the `mdpiper/bmi-example-c-grpc4bmi-154` image).
(e.g., try the `csdms/bmi-example-c-grpc4bmi` image).

For more in-depth examples of running the *Heat* model through grpc4bmi,
see the [examples](./examples) directory.

## Developer notes

A versioned, multiplatform image built from the *conda-base* image in this repository is hosted on Docker Hub
at [csdms/bmi-example-c-grpc4bmi](https://hub.docker.com/r/csdms/bmi-example-c-grpc4bmi).
This image is automatically built and pushed to Docker Hub
with the [release](./.github/workflows/release.yml) CI workflow.
The workflow is only run when the repository is tagged.
To manually build and push an update, run:
```
docker buildx build --platform linux/amd64,linux/arm64 -t csdms/bmi-example-c-grpc4bmi:latest --push .
```
A user can pull this image from Docker Hub with:
```
docker pull csdms/bmi-example-c-grpc4bmi
```
optionally with the `latest` tag or with a version tag.

## Acknowledgment

This work is supported by the U.S. National Science Foundation under Award No. [2103878](https://www.nsf.gov/awardsearch/showAward?AWD_ID=2103878), *Frameworks: Collaborative Research: Integrative Cyberinfrastructure for Next-Generation Modeling Science*.
22 changes: 22 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# examples

Two examples--a [Python script](./run-model-through-grpc4bmi.py)
and a [Jupyter notebook](./run-model-through-grpc4bmi.ipynb)--that demonstrate how to run
the C `Heat` model through the grpc4bmi server built in this project.

In a virtual environment,
install grpc4bmi and other dependencies:
```sh
pip install -r requirements.txt
```

Run the Python example:
```sh
python run-model-through-grpc4bmi.py
```
It'll produce output in the terminal.

Start JupyterLab and run the example notebook:
```sh
jupyter lab run-model-through-grpc4bmi.ipynb
```
2 changes: 1 addition & 1 deletion examples/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
grpc4bmi
numpy
jupyter
2 changes: 1 addition & 1 deletion examples/run-model-through-grpc4bmi.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@
"metadata": {},
"outputs": [],
"source": [
"DOCKER_IMAGE = \"mdpiper/bmi-example-c-grpc4bmi-154\"\n",
"DOCKER_IMAGE = \"csdms/bmi-example-c-grpc4bmi:latest\"\n",
"BMI_PORT = 55555\n",
"CONFIG_FILE = pathlib.Path(\"/opt/bmi-example-c\") / \"testing\" / \"config.txt\""
]
Expand Down
4 changes: 2 additions & 2 deletions examples/run-model-through-grpc4bmi.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# Run the C `Heat` model in Python through [grpc4bmi](https://grpc4bmi.readthedocs.io).
#
# `Heat` models the diffusion of temperature on a uniform rectangular plate with Dirichlet boundary conditions.
# View the model source code and its BMI at https://github.com/csdms/bmi-example-cxx.
# View the model source code and its BMI at https://github.com/csdms/bmi-example-c.

# Start by importing some helper libraries.
import os
Expand All @@ -16,7 +16,7 @@
# * which Docker image to use,
# * the port exposed through the image, and
# * the location in the image of the configuration file used for the model.
DOCKER_IMAGE = "mdpiper/bmi-example-c-grpc4bmi-154"
DOCKER_IMAGE = "csdms/bmi-example-c-grpc4bmi"
BMI_PORT = 55555
CONFIG_FILE = pathlib.Path("/opt/bmi-example-c") / "testing" / "config.txt"

Expand Down
17 changes: 17 additions & 0 deletions images/conda-base/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# A grpc4bmi server for the bmi-example-c `Heat` model.
FROM csdms/grpc4bmi:0.3.0

LABEL org.opencontainers.image.authors="Mark Piper <mark.piper@colorado.edu>"
LABEL org.opencontainers.image.source="https://github.com/csdms/bmi-example-cxx-grpc4bmi"

COPY server /opt/heatc-grpc4bmi-server
WORKDIR /opt/heatc-grpc4bmi-server/_build
RUN cmake .. -DCMAKE_INSTALL_PREFIX=${CONDA_DIR} && \
make && \
make install && \
make clean

WORKDIR /opt

ENTRYPOINT ["/opt/conda/bin/heatc-grpc4bmi-server"]
EXPOSE 55555
4 changes: 4 additions & 0 deletions images/conda-base/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# conda-base

This is the version of *bmi-example-c-grpc4bmi* built on conda-forge packages.
See the top-level [README](../../README.md) for more information on building this image.
45 changes: 45 additions & 0 deletions images/conda-base/server/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# bmi-example-c-grpc4bmi

cmake_minimum_required(VERSION 3.16)
project(bmi-example-cxx-grpc4bmi
VERSION 0.1.0
LANGUAGES CXX
)

include(GNUInstallDirs)

find_package(PkgConfig REQUIRED)

pkg_check_modules(BMIHEATC REQUIRED IMPORTED_TARGET bmiheatc)
list(APPEND CMAKE_MESSAGE_INDENT " ")
message(STATUS "Include directory: ${BMIHEATC_INCLUDE_DIRS}")
message(STATUS "Library path: ${BMIHEATC_LINK_LIBRARIES}")
list(POP_BACK CMAKE_MESSAGE_INDENT)

pkg_check_modules(PROTOBUF REQUIRED IMPORTED_TARGET protobuf)
list(APPEND CMAKE_MESSAGE_INDENT " ")
message(STATUS "Include directory: ${PROTOBUF_INCLUDE_DIRS}")
message(STATUS "Library path: ${PROTOBUF_LINK_LIBRARIES}")
list(POP_BACK CMAKE_MESSAGE_INDENT)

pkg_check_modules(GRPC4BMI REQUIRED IMPORTED_TARGET grpc4bmi)
list(APPEND CMAKE_MESSAGE_INDENT " ")
message(STATUS "Include directory: ${GRPC4BMI_INCLUDE_DIRS}")
message(STATUS "Library path: ${GRPC4BMI_LINK_LIBRARIES}")
list(POP_BACK CMAKE_MESSAGE_INDENT)

set(server_exe heatc-grpc4bmi-server)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -lgrpc++_reflection")

add_executable(${server_exe} ${server_exe}.cxx)
target_link_libraries(${server_exe}
${BMIHEATC_LINK_LIBRARIES}
${PROTOBUF_LINK_LIBRARIES}
${GRPC4BMI_LINK_LIBRARIES}
)
target_include_directories(${server_exe} PUBLIC ${GRPC4BMI_INCLUDE_DIRS})

install(
TARGETS ${server_exe}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
7 changes: 3 additions & 4 deletions Dockerfile → images/source-base/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
# grpc4bmi server for the `HeatC` model from bmi-example-c.
FROM mdpiper/grpc4bmi-154
# A grpc4bmi server for the bmi-example-c `Heat` model.
FROM mdpiper/grpc4bmi

LABEL maintainer="Mark Piper <mark.piper@colorado.edu>"

RUN git clone --branch v2.0.3 --depth 1 https://github.com/csdms/bmi-example-c /opt/bmi-example-c
WORKDIR /opt/bmi-example-c/_build
RUN cmake .. && \
make && \
make test && \
ctest -V && \
make install && \
make clean

# Build the grpc4bmi server for the `heatc` model.
COPY server /opt/heatc-grpc4bmi-server
WORKDIR /opt/heatc-grpc4bmi-server/_build
RUN cmake .. && \
Expand Down
5 changes: 5 additions & 0 deletions images/source-base/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# source-base

This is the version of *bmi-example-c-grpc4bmi* built from source.
See the top-level [README](../../README.md) for more information
on building this image.
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,11 @@ list(POP_BACK CMAKE_MESSAGE_INDENT)
set(server_exe heatc-grpc4bmi-server)

add_executable(${server_exe} ${server_exe}.cxx)
target_link_libraries(${server_exe} ${BMIHEATC_LINK_LIBRARIES} ${PROTOBUF_LINK_LIBRARIES} ${GRPC4BMI_LINK_LIBRARIES})
target_link_libraries(${server_exe}
${BMIHEATC_LINK_LIBRARIES}
${PROTOBUF_LINK_LIBRARIES}
${GRPC4BMI_LINK_LIBRARIES}
)
target_include_directories(${server_exe} PUBLIC ${GRPC4BMI_INCLUDE_DIRS})

install(
Expand Down
26 changes: 26 additions & 0 deletions images/source-base/server/heatc-grpc4bmi-server.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#include <stdio.h>

#include "bmi_heat.h"
#include "bmi_grpc_server.h"


int main(int argc, char *argv[])
{
printf("BmiHeat C grpc4bmi server\n");

Bmi *model = (Bmi *) malloc(sizeof(Bmi));

register_bmi_heat(model);

{
char model_name[BMI_MAX_COMPONENT_NAME];

model->get_component_name(model, model_name);
printf("%s\n", model_name);
}

run_bmi_server(model, argc, argv);

free(model);
return 0;
}