-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Implement Fast API optional component (#117) * added Fast API optional component Signed-off-by: Dixon Whitmire <[email protected]> * updating version number Signed-off-by: Dixon Whitmire <[email protected]> * updating CI to test on Python 3.9 and 3.10 (#118) Signed-off-by: Dixon Whitmire <[email protected]> * X12 Image Build (#121) * adding Dockerfile for image build Signed-off-by: Dixon Whitmire <[email protected]> * updating GitHub workflows Signed-off-by: Dixon Whitmire <[email protected]> * updating image ci to use build-args Signed-off-by: Dixon Whitmire <[email protected]> * configuring PR based image CI to build a single image to reduce wait times Signed-off-by: Dixon Whitmire <[email protected]> * updating image build ci Signed-off-by: Dixon Whitmire <[email protected]> * removing Dockerfile path condition since it's not working Signed-off-by: Dixon Whitmire <[email protected]> * Updated container support documentation (#127) Signed-off-by: Dixon Whitmire <[email protected]> * update /x12 [POST] endpoint segment mode to return an equivalent response as the CLI in segment mode (#129) Signed-off-by: Dixon Whitmire <[email protected]> * adding script to build and push multi-platform images (#130) Signed-off-by: Dixon Whitmire <[email protected]> * removing tag version from GitHub actions Signed-off-by: Dixon Whitmire <[email protected]>
- Loading branch information
1 parent
3734589
commit c97b41a
Showing
13 changed files
with
421 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
.github | ||
.idea | ||
.vscode | ||
**/.pytest_cache | ||
**/linuxforhealth_x12.egg-info | ||
demo-file | ||
repo-docs | ||
**/tests | ||
venv | ||
.gitignore | ||
LICENSE |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
name: Test X12 Image Build | ||
|
||
on: | ||
push: | ||
branches: [ main ] | ||
pull_request: | ||
branches: [ main ] | ||
|
||
jobs: | ||
build-image: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Check out the repo | ||
uses: actions/checkout@v3 | ||
- name: QEMU setup | ||
uses: docker/setup-qemu-action@v2 | ||
- name: Docker buildx setup | ||
uses: docker/setup-buildx-action@v2 | ||
- name: Build and push Docker image | ||
uses: docker/build-push-action@v3 | ||
with: | ||
context: . | ||
build-args: | | ||
X12_SEM_VER=0.57.0 | ||
platforms: linux/amd64 | ||
push: false | ||
tags: ci-testing |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
# Builds the LinuxForHealth X12 API container using a multi-stage build | ||
|
||
# build stage | ||
FROM python:3.10-slim-buster AS builder | ||
|
||
# the full semantic version number, used to match to the generated wheel file in dist/ | ||
ARG X12_SEM_VER | ||
|
||
# OS library updates and build tooling | ||
RUN apt-get update | ||
RUN apt-get install -y --no-install-recommends \ | ||
build-essential \ | ||
gcc | ||
|
||
# copy source and build files | ||
WORKDIR /tmp/lfh-x12 | ||
COPY setup.cfg . | ||
COPY pyproject.toml . | ||
COPY ../src src/ | ||
|
||
# build the service | ||
RUN python -m venv /tmp/lfh-x12/venv | ||
ENV PATH="/tmp/lfh-x12/venv/bin:$PATH" | ||
RUN python -m pip install --upgrade pip setuptools wheel build | ||
RUN python -m build | ||
RUN python -m pip install dist/linuxforhealth_x12-"$X12_SEM_VER"-py3-none-any.whl[api] | ||
|
||
# main image | ||
FROM python:3.10-slim-buster | ||
|
||
# container build arguments | ||
# lfh user id and group ids | ||
ARG LFH_USER_ID=1000 | ||
ARG LFH_GROUP_ID=1000 | ||
|
||
# create service user and group | ||
RUN groupadd -g $LFH_GROUP_ID lfh && \ | ||
useradd -m -u $LFH_USER_ID -g lfh lfh | ||
USER lfh | ||
WORKDIR /home/lfh | ||
|
||
# configure and execute application | ||
COPY --from=builder /tmp/lfh-x12/venv ./venv | ||
# set venv executables first in path | ||
ENV PATH="/home/lfh/venv/bin:$PATH" | ||
# listening address for application | ||
ENV X12_UVICORN_HOST=0.0.0.0 | ||
EXPOSE 5000 | ||
CMD ["python", "-m", "linuxforhealth.x12.api"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
ISA*03*9876543210*01*9876543210*30*000000005 *30*12345 *131031*1147*^*00501*000000907*1*T*:~GS*HS*000000005*54321*20131031*1147*1*X*005010X279A1~ST*270*1234*005010X279A1~BHT*0022*13*10001234*20060501*1319~HL*1**20*1~NM1*PR*2*ABC COMPANY*****PI*842610001~HL*2*1*21*1~NM1*1P*2*BONE AND JOINT CLINIC*****SV*2000035~HL*3*2*22*0~TRN*1*93175-012547*9877281234~NM1*IL*1*SMITH*ROBERT****MI*11122333301~DMG*D8*19430519~DTP*291*D8*20060501~EQ*30~SE*13*1234~GE*1*1~IEA*1*000000907~ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
#!/bin/bash | ||
# push-image.sh | ||
# push-image.sh builds and pushes the multi-platform linuxforhealth/x12 image to an image repository. | ||
# | ||
# Pre-Requisites: | ||
# - The script environment is authenticated to the target image repository. | ||
# - The project has been built and a wheel exists in <project root>/dist. | ||
# | ||
# Usage: | ||
# ./push-image [image_tag] [image_url] [platforms] | ||
# | ||
# Positional Script arguments: | ||
# IMAGE_TAG - Aligns with the project's semantic version. Required. | ||
# IMAGE_URL - The image's URL. Defaults to ghcr.io/linuxforhealth/x12. | ||
# PLATFORMS - String containing the list of platforms. Defaults to linux/amd64,linux/arm64,linux/s390x. | ||
|
||
set -o errexit | ||
set -o nounset | ||
set -o pipefail | ||
|
||
if [[ $# == 0 ]] | ||
then | ||
echo "Missing required argument IMAGE_TAG" | ||
echo "Usage: ./push-image.sh [image tag] [image url] [platforms]" | ||
exit 1; | ||
fi | ||
|
||
IMAGE_TAG=$1 | ||
IMAGE_URL="${2:-ghcr.io/linuxforhealth/x12}" | ||
PLATFORMS="${3:-linux/amd64,linux/arm64,linux/s390x}" | ||
|
||
docker buildx build \ | ||
--pull \ | ||
--push \ | ||
--platform "$PLATFORMS" \ | ||
--build-arg X12_SEM_VER="$IMAGE_TAG" \ | ||
--tag "$IMAGE_URL":"$IMAGE_TAG" \ | ||
--tag "$IMAGE_URL":latest . |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
# LinuxForHealth X12 Container Support | ||
|
||
The LinuxForHealth X12 API component supports a containerized execution environment. This guide provides an overview of | ||
how to build and run the image. | ||
|
||
## Image Build | ||
|
||
### Supported Build Arguments | ||
|
||
|
||
| Build Argument | Description | Default Value | | ||
|----------------|------------------------------------------------|---------------| | ||
| X12_SEM_VER | The current X12 library sematic version number | None | | ||
| LFH_USER_ID | The user id used for the LFH container user | 1000 | | ||
| LFH_GROUP_ID | The group id used for the LFH container group | 1000 | | ||
|
||
The `X12_SEM_VER`. This argument should align with the current `linuxforhealth.x12.__version__` attribute value and the | ||
desired image tag. | ||
|
||
```shell | ||
docker build --build-arg X12_SEM_VER=0.57.0 -t x12:0.57.0 . | ||
``` | ||
|
||
## Run Container | ||
|
||
### Supported Environment Configurations | ||
|
||
| Build Argument | Description | Default Value | | ||
|------------------|-----------------------------------|---------------| | ||
| X12_UVICORN_HOST | The container's listening address | 0.0.0.0 | | ||
|
||
|
||
The following command launches the LinuxForHealth X12 container: | ||
```shell | ||
docker run --name lfh-x12 --rm -d -p 5000:5000 ghcr.io/linuxforhealth/x12:latest | ||
``` | ||
|
||
To access the Open API UI, browse to http://localhost:5000/docs | ||
|
||
Finally, to stop and remove the container: | ||
```shell | ||
docker stop lfh-x12 | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,4 +7,4 @@ | |
|
||
load_dotenv() | ||
|
||
__version__ = "0.56.02" | ||
__version__ = "0.57.0" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
from fastapi import FastAPI, Header, HTTPException, Request, status | ||
from fastapi.exceptions import RequestValidationError | ||
from fastapi.responses import JSONResponse | ||
from fastapi.encoders import jsonable_encoder | ||
import uvicorn | ||
from typing import Dict, Optional, List | ||
from linuxforhealth.x12.config import get_x12_api_config, X12ApiConfig | ||
from linuxforhealth.x12.io import X12SegmentReader, X12ModelReader | ||
from linuxforhealth.x12.parsing import X12ParseException | ||
from pydantic import ValidationError, BaseModel, Field | ||
|
||
app = FastAPI() | ||
|
||
|
||
@app.exception_handler(RequestValidationError) | ||
async def request_validation_handler(request: Request, exc: RequestValidationError): | ||
return JSONResponse( | ||
status_code=status.HTTP_400_BAD_REQUEST, | ||
content=jsonable_encoder( | ||
{"detail": "Invalid request. Expected {'x12': <x12 message string>}"} | ||
), | ||
) | ||
|
||
|
||
class X12Request(BaseModel): | ||
""" | ||
The X12 Request object | ||
""" | ||
|
||
x12: str = Field(description="The X12 payload to process, conveyed as a string") | ||
|
||
class Config: | ||
schema_extra = { | ||
"example": { | ||
"x12": "ISA*03*9876543210*01*9876543210*30*000000005 *30*12345 *131031*1147*^*00501*000000907*1*T*:~GS*HS*000000005*54321*20131031*1147*1*X*005010X279A1~ST*270*1234*005010X279A1~BHT*0022*13*10001234*20060501*1319~HL*1**20*1~NM1*PR*2*ABC COMPANY*****PI*842610001~HL*2*1*21*1~NM1*1P*2*BONE AND JOINT CLINIC*****SV*2000035~HL*3*2*22*0~TRN*1*93175-012547*9877281234~NM1*IL*1*SMITH*ROBERT****MI*11122333301~DMG*D8*19430519~DTP*291*D8*20060501~EQ*30~SE*13*1234~GE*1*1~IEA*1*000000907~", | ||
} | ||
} | ||
|
||
|
||
@app.post("/x12") | ||
async def post_x12( | ||
x12_request: X12Request, | ||
lfh_x12_response: Optional[str] = Header(default="models"), | ||
) -> List[Dict]: | ||
""" | ||
Processes an incoming X12 payload. | ||
Requests are submitted as: | ||
{ | ||
"x12": <x12 message string> | ||
} | ||
The response payload is a JSON document containing either the "raw" X12 segments, or a rich | ||
X12 domain model. The response type defaults to the domain model and is configured using the | ||
LFH-X12-RESPONSE header. Valid values include: "segments" or "models". | ||
:param x12_request: The X12 request model/object. | ||
:param lfh_x12_response: A header value used to drive processing. | ||
:return: The X12 response - List[List] (segments) or List[Dict] (models) | ||
""" | ||
if lfh_x12_response.lower() not in ("models", "segments"): | ||
lfh_x12_response = "models" | ||
|
||
try: | ||
if lfh_x12_response.lower() == "models": | ||
with X12ModelReader(x12_request.x12) as r: | ||
api_results = [m.dict() for m in r.models()] | ||
else: | ||
with X12SegmentReader(x12_request.x12) as r: | ||
api_results = [] | ||
for segment_name, segment in r.segments(): | ||
segment_data = { | ||
f"{segment_name}{str(i).zfill(2)}": v | ||
for i, v in enumerate(segment) | ||
} | ||
api_results.append(segment_data) | ||
|
||
except (X12ParseException, ValidationError) as error: | ||
raise HTTPException( | ||
status_code=status.HTTP_400_BAD_REQUEST, | ||
detail="Invalid X12 payload. To troubleshoot please run the LFH X12 CLI", | ||
) | ||
else: | ||
return api_results | ||
|
||
|
||
def run_server(): | ||
"""Launches the API server""" | ||
config: X12ApiConfig = get_x12_api_config() | ||
|
||
uvicorn_params = { | ||
"app": config.x12_uvicorn_app, | ||
"host": config.x12_uvicorn_host, | ||
"port": config.x12_uvicorn_port, | ||
"reload": config.x12_uvicorn_reload, | ||
} | ||
|
||
uvicorn.run(**uvicorn_params) | ||
|
||
|
||
if __name__ == "__main__": | ||
run_server() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.