Skip to content

Commit

Permalink
add linting and ci, automated container build, demo docs (#3)
Browse files Browse the repository at this point in the history
* add linting and ci, automated container build, demo docs
Signed-off-by: vsoch <[email protected]>
  • Loading branch information
vsoch authored Nov 4, 2022
1 parent f18c166 commit 12a1d6e
Show file tree
Hide file tree
Showing 27 changed files with 360 additions and 103 deletions.
12 changes: 10 additions & 2 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ LABEL maintainer="Vanessasaurus <@vsoch>"

# Pip not provided in this version
USER root
RUN apt-get update
RUN apt-get update && apt-get install -y python3-venv
COPY ./requirements.txt /requirements.txt
COPY ./dev-requirements.txt /dev-requirements.txt
COPY ./.github/dev-requirements.txt /dev-requirements.txt

EXPOSE 5000
ENV PYTHONPATH=/usr/lib/flux/python3.8
Expand All @@ -15,3 +15,11 @@ ENV PYTHONPATH=/usr/lib/flux/python3.8
RUN python3 -m pip install IPython && \
python3 -m pip install -r /requirements.txt && \
python3 -m pip install -r /dev-requirements.txt

# Install isort and ensure on path
RUN python3 -m venv /env && \
. /env/bin/activate && \
pip install -r /requirements.txt && \
pip install -r /dev-requirements.txt

ENV PATH=/env/bin:${PATH}
File renamed without changes.
50 changes: 50 additions & 0 deletions .github/workflows/build-deploy.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
name: Build Deploy Containers

on:

# Publish packages on release
release:
types: [published]

pull_request: []

# On push to main we build and deploy images
push:
branches:
- main

jobs:
build:
env:
container: ghcr.io/flux-framework/flux-restful-api
permissions:
packages: write

runs-on: ubuntu-latest
name: Build
steps:
- name: Checkout
uses: actions/checkout@v3

- name: Build Container
run: docker build -t ${{env.container}} .

- name: GHCR Login
if: (github.event_name != 'pull_request')
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Tag and Push Release Image
if: (github.event_name == 'release')
run: |
tag=${GITHUB_REF#refs/tags/}
echo "Tagging and releasing ${{ env.container }}:${tag}"
docker tag ${{env.container}}:latest ${{env.container}}:${tag}
docker push ${{env.container}}:${tag}
- name: Deploy
if: (github.event_name != 'pull_request')
run: docker push ${{env.container}}:latest
29 changes: 29 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: flux-restful-api

on:
# This should run on a push to any branch except main, gh-pages, and binoc
push:
branches-ignore:
- main
- gh-pages

jobs:
formatting:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3

- name: Setup black linter
run: conda create --quiet --name black pyflakes

- name: Check Spelling
uses: crate-ci/typos@7ad296c72fa8265059cc03d1eda562fbdfcd6df2 # v1.9.0
with:
files: ./README.md

- name: Lint and format Python code
run: |
export PATH="/usr/share/miniconda/bin:$PATH"
source activate black
pip install -r .github/dev-requirements.txt
pre-commit run --all-files
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
env
.env
__pycache__
*.tar.gz
*.tar.gz
32 changes: 32 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
exclude: ".all-contributorsrc"
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.3.0
hooks:
- id: check-added-large-files
- id: check-case-conflict
- id: check-docstring-first
- id: end-of-file-fixer
- id: trailing-whitespace
- id: mixed-line-ending

- repo: local
hooks:
- id: black
name: black
language: python
types: [python]
entry: black

- id: isort
name: isort
args: [--filter-files]
language: python
types: [python]
entry: isort

- id: flake8
name: flake8
language: python
types: [python]
entry: flake8
29 changes: 29 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
FROM fluxrm/flux-sched:focal

# docker build -t ghcr.io/flux-framework/flux-restful-api .

ARG user
ARG token
ARG use_auth
ARG port="5000"
ARG host="0.0.0.0"
LABEL maintainer="Vanessasaurus <@vsoch>"

USER root
RUN apt-get update
COPY ./requirements.txt /requirements.txt

EXPOSE ${port}
ENV PYTHONPATH=/usr/lib/flux/python3.8

# For easier Python development.
RUN python3 -m pip install -r /requirements.txt

WORKDIR /code
COPY . /code
ENV FLUX_USER=${user}
ENV FLUX_TOKEN=${token}
ENV FLUX_REQUIRE_AUTH=${use_auth}
ENV PORT=${port}
ENV HOST=${host}
ENTRYPOINT ["/code/entrypoint.sh"]
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
GNU Lesser General Public License
=================================

_Version 3, 29 June 2007_
_Version 3, 29 June 2007_
_Copyright Β© 2007 Free Software Foundation, Inc. &lt;<http://fsf.org/>&gt;_

Everyone is permitted to copy and distribute verbatim copies
Expand Down
100 changes: 85 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ alongside Flux, and provide an easy means to interact with Flux via the API.
My goals are:

1. provide simple endpoints to submit jobs, list jobs, or get job status
2. eventually support subscribing to events
2. eventually support subscribing to events and a user interface job table
3. option to kill or stop the server (intended for Flux Operator)
4. allow for start with a user name and token (for basic auth)

Expand All @@ -23,16 +23,92 @@ that would be really cool (and is what I plan to test.)

![img/flux-restful.png](img/flux-restful.png)

**under development!**
🚧️ **under development!** 🚧️

## Usage

### Devcontainer

If you use VSCode a [.devcontainer](.devcontainer) recipe is available that makes it easy to
spin up an environment just by way of opening the respository in VSCode! After doing
spin up an environment just by way of opening the repository in VSCode! After doing
this, continue to [Local](#Local) below.

### Docker

You can use the [demo container](https://github.com/flux-framework/flux-restful-api/pkgs/container/flux-restful-api),
either as provided or build on your own, to
run the server and interact with it. To optionally build the container:

```bash
$ docker build -t ghcr.io/flux-framework/flux-restful-api .
```

To build ensuring there is authentication:

```bash
$ docker build --build-arg user=fluxuser --build-arg token=12345 --build-arg use_auth=true -t ghcr.io/flux-framework/flux-restful-api .
```

Build arguments supported are:

| Name | Description | Default |
|------|-------------|---------|
| user | Username for basic auth | unset |
| token | Token password for basic auth | unset |
| use_auth | Turn on authentication | unset (meaning false) |
| port | Port to run service on (and expose) | 5000 |
| host | Host to run service on (you probably shouldn't change this) |0.0.0.0 |

And run it ensuring you expose port 5000. The container should show you if you've
correctly provided auth (or not):

```bash
$ docker run --rm -it -p 5000:5000 ghcr.io/flux-framework/flux-restful-api
```
```console
πŸ“ Require auth: True
πŸ“ Flux user: ********
πŸ“ Flux token: *****
INFO: Started server process [72]
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: Uvicorn running on http://0.0.0.0:5000 (Press CTRL+C to quit)
```

Or run detached and then stop later:

```bash
$ docker run --name flux-restful -d --rm -it -p 5000:5000 ghcr.io/flux-framework/flux-restful-api
$ docker stop flux-restful
```


Either way, you can open your host to [http://127.0.0.1:5000](http://127.0.0.1:5000)
to see the very simple interface! This currently has API documentation (Openschema)
and we will soon add a table of jobs.

![img/portal.png](img/portal.png)

Once you have the server running, you can test out the example scripts!
You'll minimally need requests installed:

```bash
$ pip install requests
```

You should export the same flux user and password token if you added authentication:

```bash
$ export FLUX_USER=fluxuser
$ export FLUX_TOKEN=12345
```
```bash
$ python
```


See the [examples](examples) folder for more functionality.

### Local

You can use this setup locally (if you have flux and Python available) or within the Dev Container
Expand Down Expand Up @@ -75,7 +151,7 @@ For the latter, you can also use the Makefile:
$ make
```
If you are developing, you must do the second approach as the server won't live-update
with the first.
with the first.

#### 3. Authentication

Expand Down Expand Up @@ -114,16 +190,16 @@ after it:
from flux_restful_client import FluxRestfulClient

# create with username and token
cli = FluxRestfulClient(user="fluxuser", token="12345")
cli = FluxRestfulClient(user="fluxuser", token="12345")

# Add or update after creation
cli.set_basic_auth(user="fluxuser", token="12345")
cli.set_basic_auth(user="fluxuser", token="12345")
```
In addition, you can set the hostname (which defaults to localhost on port 5000):

```python
# create with username and token
cli = FluxRestfulClient('http://127.0.0.1:5000')
cli = FluxRestfulClient('http://127.0.0.1:5000')
```

See the [examples](examples) folder for a mix of example (one with submit with auth)!
Expand All @@ -146,13 +222,9 @@ and thus exit the job and bring down the mini-cluster.

List jobs owned by the flux executor (the current user).

##### GET `/jobs`

List jobs owned by the flux executor (the current user).

##### GET `/jobs/{uid}`

Get a job with a specific identifer.
Get a job with a specific identifier.

##### POST `/jobs/{uid}/cancel`

Expand All @@ -177,7 +249,7 @@ List cluster nodes.
Install development requirements:

```bash
$ pip install -r dev-requirements.txt
$ pip install -r .github/dev-requirements.txt
```
And then run pre-commit manually, or install:

Expand Down Expand Up @@ -212,8 +284,6 @@ tool to generate a contributors graphic below.
## TODO

- Interface view with nice job table
- pre-commit and workflows to run it
- Docker container with demo to run example
- We can put additional assets for the server in [data](data), not sure what those are yet!

#### Release
Expand Down
3 changes: 2 additions & 1 deletion app/core/config.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from pydantic import BaseSettings
import os

from pydantic import BaseSettings


class Settings(BaseSettings):
app_name: str = "Flux RESTFul API"
Expand Down
16 changes: 10 additions & 6 deletions app/library/auth.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
from fastapi import HTTPException, Depends, status
from app.core.config import settings
import logging
import secrets

from fastapi import Depends, HTTPException, status
from fastapi.security import HTTPBasic, HTTPBasicCredentials
import secrets
import logging

from app.core.config import settings

logger = logging.getLogger(__name__)

Expand All @@ -23,16 +24,19 @@ def alert_auth():
print(
"πŸ“ Flux user: %s" % ("*" * len(settings.flux_user))
if settings.flux_user
else "unset"
else "πŸ“ Flux user: unset"
)
print(
"πŸ“ Flux token: %s" % ("*" * len(settings.flux_token))
if settings.flux_token
else "unset"
else "πŸ“ Flux token: unset"
)


def check_auth(credentials: HTTPBasicCredentials = Depends(security)):
"""
Check base64 encoded auth (this is HTTP Basic auth.)
"""
if not settings.flux_user or not settings.flux_token:
return not_authenticated("Missing FLUX_USER and/or FLUX_TOKEN")
current_username_bytes = credentials.username.encode("utf8")
Expand Down
Loading

0 comments on commit 12a1d6e

Please sign in to comment.