Skip to content

Commit

Permalink
Merge pull request #112 from SURFscz/docker
Browse files Browse the repository at this point in the history
Docker
  • Loading branch information
baszoetekouw authored Oct 9, 2023
2 parents 569b9b0 + bc7fbb5 commit 974e0b6
Show file tree
Hide file tree
Showing 7 changed files with 175 additions and 21 deletions.
8 changes: 8 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.vscode
.editorignore
.flake*
.git*
.python*
Dockerfile
Makefile
etc
42 changes: 42 additions & 0 deletions .github/workflows/image.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#
name: Create and publish a Docker image

on:
push:
branches: ["docker"]

env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}

jobs:
build-and-push-image:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Log in to the Container registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}

- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,4 @@ tests/api/
.theia/
plsc.yaml
.python-version
Pipfile
Pipfile
23 changes: 23 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
ARG PYTHON_VERSION=3.11-alpine

FROM python:${PYTHON_VERSION}

RUN apk add py3-virtualenv py3-pytest python3-dev gcc musl-dev openldap-dev bash

ENV VENV /.venv
RUN virtualenv ${VENV}
ENV PATH ${VENV}/bin:$PATH

RUN adduser -D user

WORKDIR /app

ADD . .
RUN chown -R user:user ${VENV} .

USER user

RUN pip install --upgrade pip
RUN pip install -r requirements.txt

CMD ["./run.sh"]
20 changes: 20 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Makefile

all: pytest

image:
docker build -t plsc .

ldap_start:
etc/ldap_start.sh

ldap_show:
etc/ldap_show.sh

ldap_stop:
etc/ldap_stop.sh

pytest: image ldap_start
docker run --rm -ti --network host plsc pytest

clean: ldap_stop
56 changes: 45 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ For local development we advice to make use of Python Virtual Environment. The i
This is an example of what we need to specify source and destination.
[ More complex examples will follow ]

```
```bash
---
ldap:
src:
Expand All @@ -34,18 +34,21 @@ src:
### Local development

Create a virtual environment and install the required python packages:
```

```bash
python3 -m venv .venv
source .venv/bin/activate
pip install --upgrade pip
pip install -r requirements.txt
```

### Use
```sync_services``` will look for all ```labeledURI``` attributes in the source and create ```dc=<labeledURI>``` branches on the destination containing all CO's that are linked to these services with bare ```People```, ```Groups``` and ```uid/gidNumberSequence``` structures.

```plsc``` will then mirror all ```People``` and ```Groups``` to the corresponding CO's in the destination LDAP, optionally converting attributes and dn's as defined in the code on the way:
```
`sync_services` will look for all `labeledURI` attributes in the source and create `dc=<labeledURI>` branches on the destination containing all CO's that are linked to these services with bare `People`, `Groups` and `uid/gidNumberSequence` structures.

`plsc` will then mirror all `People` and `Groups` to the corresponding CO's in the destination LDAP, optionally converting attributes and dn's as defined in the code on the way:

```bash
# Here's the magic: Build the new person entry
dst_entry = {}
dst_entry['objectClass'] = ['inetOrgPerson', 'person', 'posixAccount']
Expand All @@ -56,7 +59,8 @@ pip install -r requirements.txt
```

And for groups:
```

```bash
# Here's the magic: Build the new group entry
m = re.search('^(?:GRP)?(?:CO)?(?:COU)?:(.*?)$', src_cn)
dst_cn = src_type + "_" + m.group(1) if m.group(1) else ""
Expand All @@ -72,7 +76,7 @@ And for groups:
For local testing, you need a local LDAP to be started before running tests.
When you have docker installed on your local machine, you can simple run:
```
```bash
etc/ldap_start.sh
```
Expand All @@ -82,7 +86,7 @@ If you do not have docker installed or wish to use an existing running LDAP serv
You can specify LDAP connection and access constants in a local **.env** file, for exanple:
```
```bash
LDAP_URL="ldap://localhost:389"
LDAP_ADMIN_PASSWORD="secret"
LDAP_CONFIG_PASSWORD="config"
Expand All @@ -106,20 +110,50 @@ When you omit the **SBS_URL** variable, the tests will run API requests agains t
When all these preperations are completed, you can now run the tests:
```
```bash
pytest -v
```
After each Test cycle the contents of the LDAP can be inspected, for that run this command:
```
```bash
etc/ldap_show.sh
```
When finished you can tear down the local running LDAP instance, by:
```
```bash
etc/ldap_stop.sh
```
# Using Make
A Makefile is added to make life easier. Now you can run:
```bash
make pytest
```
Or just make. This will build the docker image and run pytest next.
```bash
make
```
# Docker
A Dockerfile is added to produce an image that is capable of running PLSC. Since PLSC depends on an input YAML file holding the source and destionatination details, you have to provide sucan YANL file.
Using Docker you can do the following:
Suppose you have prepared you YAML file (inspired by plsc.yml.example) and this file is 'my-plsc.yml'
You have to mount this file into the container and then run **run.sh** with that file as parameter.
Example:
```bash
docker run -v ${pwd}/my-plsc.yml:/tmp/plsc.yaml plsc ./run.sh /tmp/plsc.yml
```
**run.sh** is the existing script that runs both _plsc_ordered.py_ and _plsc_flat_
45 changes: 36 additions & 9 deletions tests/base_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

from aiohttp import web

from gera2ld.pyserve import run_forever, start_server_aiohttp

from sldap import SLdap
from sbs import SBS

Expand Down Expand Up @@ -47,6 +45,7 @@ def do_get(request):
return web.json_response({}, status=404)


DEFAULT_LOCAL_HOST = '127.0.0.1'
DEFAULT_LOCAL_PORT = 3333


Expand All @@ -72,23 +71,49 @@ class BaseTest(TestCase):
@classmethod
def setUpClass(cls):
def start_server(loop):

async def init_api_server(handle, host, port):
server = web.ServerRunner(web.Server(handle))
await server.setup()

site = web.TCPSite(
server,
host=host,
port=port
)
await site.start()

return server

logger.debug("BaseTest start_server")
handle = APIHandler()
asyncio.set_event_loop(loop)
run_forever(start_server_aiohttp(handle, ':{}'.format(DEFAULT_LOCAL_PORT)))

api_server = init_api_server(
APIHandler(),
DEFAULT_LOCAL_HOST,
DEFAULT_LOCAL_PORT
)

try:
loop.run_until_complete(api_server)
loop.run_forever()
finally:
loop.close()

def check_server():
logger.debug("BaseTest check_server")
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(1)
while sock.connect_ex(('127.0.0.1', DEFAULT_LOCAL_PORT)) == 111:
while sock.connect_ex(
(DEFAULT_LOCAL_HOST, DEFAULT_LOCAL_PORT)
) == 111:
time.sleep(0.1)

if not os.environ.get("SBS_URL", None):
logger.debug("BaseTest setUpClass")
cls.loop = asyncio.new_event_loop()
cls.x = threading.Thread(target=start_server, args=(cls.loop,), )
cls.x.start()
cls.api = threading.Thread(target=start_server, args=(cls.loop,), )
cls.api.start()

check_server()
else:
cls.loop = None
Expand All @@ -97,8 +122,10 @@ def check_server():
def tearDownClass(cls):
if cls.loop:
logger.debug("BaseTest tearDownClass")
for task in asyncio.all_tasks(cls.loop):
task.cancel()
cls.loop.call_soon_threadsafe(cls.loop.stop)
cls.x.join()
cls.api.join()

def setUp(self):
""" Run a complete PLSC cycle, 1st ordered structure, 2nd flat structure...
Expand Down

0 comments on commit 974e0b6

Please sign in to comment.