| | |
| | | tags: |
| | | - 'v[0-9]+.*' |
| | | |
| | | permissions: |
| | | contents: read |
| | | |
| | | jobs: |
| | | deploy: |
| | | deploy-to-ghcr-io: |
| | | name: Publish to GitHub Container Registry |
| | | runs-on: ubuntu-latest |
| | | permissions: |
| | | contents: read |
| | | packages: write |
| | | steps: |
| | | - name: Checkout code |
| | | uses: actions/checkout@v6 |
| | | |
| | | - name: Log in to the Container registry |
| | | uses: docker/login-action@v4 |
| | | with: |
| | | registry: ghcr.io |
| | | username: ${{ github.actor }} |
| | | password: ${{ secrets.GITHUB_TOKEN }} |
| | | |
| | | - name: Prepare and push Docker plugin |
| | | run: | |
| | | export NAME="ghcr.io/${{ github.repository }}" |
| | | export VERSIONS="latest ${GITHUB_REF/refs\/tags\//}" |
| | | ./package.sh |
| | | |
| | | deploy-to-docker-hub: |
| | | name: Publish to Docker Hub |
| | | runs-on: ubuntu-latest |
| | | steps: |
| | | - name: Checkout code |
| | | uses: actions/checkout@v2 |
| | | uses: actions/checkout@v6 |
| | | |
| | | - name: Login to Docker Hub |
| | | run: | |
| | | docker login -u 'jacekkow' -p '${{ secrets.DOCKER_PASSWORD }}' |
| | | uses: docker/login-action@v4 |
| | | with: |
| | | username: ${{ github.actor }} |
| | | password: ${{ secrets.DOCKER_PASSWORD }} |
| | | |
| | | - name: Prepare and push Docker plugin |
| | | run: | |
| | | VERSIONS="latest ${GITHUB_REF/refs\/tags\//}" |
| | | export VERSIONS |
| | | export NAME="${{ github.actor }}/pyveth" |
| | | export VERSIONS="latest ${GITHUB_REF/refs\/tags\//}" |
| | | ./package.sh |
| | | for VERSION in ${VERSIONS}; do |
| | | docker plugin push "jacekkow/pyveth:${VERSION}" |
| | | done |
| | |
| | | branches: |
| | | - '**' |
| | | |
| | | permissions: |
| | | contents: read |
| | | |
| | | jobs: |
| | | unit_test: |
| | | name: Unit tests |
| | | runs-on: ubuntu-latest |
| | | steps: |
| | | - name: Checkout code |
| | | uses: actions/checkout@v2 |
| | | uses: actions/checkout@v6 |
| | | |
| | | - name: Set up Python |
| | | uses: actions/setup-python@v1 |
| | | uses: actions/setup-python@v6 |
| | | with: |
| | | python-version: 3.x |
| | | |
| | |
| | | VERSIONS: dev |
| | | steps: |
| | | - name: Checkout code |
| | | uses: actions/checkout@v2 |
| | | uses: actions/checkout@v6 |
| | | |
| | | - name: Prepare Docker plugin |
| | | run: | |
| | |
| | | WORKDIR /usr/src/app |
| | | |
| | | COPY --chown=nobody:nobody requirements.txt . |
| | | RUN pip3 install --user --no-cache-dir -r requirements.txt |
| | | RUN python -m venv venv && ./venv/bin/pip install --no-cache-dir -r requirements.txt |
| | | |
| | | COPY --chown=nobody:nobody . . |
| | | |
| | | CMD [ "./run.py" ] |
| | | CMD [ "./venv/bin/python", "run.py" ] |
| | |
| | | "description": "pyveth - veth network driver in Python", |
| | | "documentation": "https://github.com/jacekkow/docker-plugin-pyveth", |
| | | "workdir": "/usr/src/app", |
| | | "entrypoint": ["./run.py"], |
| | | "entrypoint": ["./venv/bin/python", "run.py"], |
| | | "env": [ |
| | | { |
| | | "name": "ENVIRONMENT", |
| | |
| | | print(ip.link("set", index=idx, master=id_parent)) |
| | | endpoint.Interface.Peer = ifname1 |
| | | |
| | | return ifname0 |
| | | return ifname0, ifname1 |
| | | |
| | | |
| | | def delete_interface(interface): |
| | | try: |
| | | with pyroute2.IPRoute() as ip: |
| | | idx = ip.link_lookup(ifname=interface)[0] |
| | | ip.link("delete", index=idx) |
| | | except: |
| | | pass |
| | | |
| | | |
| | | @app.route('/NetworkDriver.GetCapabilities', methods=['POST']) |
| | |
| | | network = networks[join.NetworkID] |
| | | endpoint = endpoints['{}-{}'.format(join.NetworkID, join.EndpointID)] |
| | | |
| | | interface = create_interface(endpoint, network) |
| | | interface, interface_external = create_interface(endpoint, network) |
| | | |
| | | endpoint.internal_interface_name = interface |
| | | endpoint.external_interface_name = interface_external |
| | | |
| | | gw4 = None |
| | | for net4 in network.IPv4: |
| | |
| | | @app.route('/NetworkDriver.Leave', methods=['POST']) |
| | | def Leave(): |
| | | leave = LeaveEntity(**flask.request.get_json(force=True)) |
| | | endpoint = endpoints.get('{}-{}'.format(leave.NetworkID, leave.EndpointID), None) |
| | | if endpoint is not None and endpoint.external_interface_name: |
| | | delete_interface(endpoint.external_interface_name) |
| | | return {} |
| | | |
| | | |
| | |
| | | #!/bin/sh |
| | | #!/bin/bash |
| | | |
| | | set -x |
| | | set -e -x |
| | | |
| | | NAME=${NAME:-jacekkow/pyveth} |
| | | VERSIONS=${VERSIONS:-latest} |
| | |
| | | sudo mkdir -p rootfs |
| | | docker export "${id}" | sudo tar -x -C rootfs |
| | | docker rm -vf "${id}" |
| | | docker plugin disable "${NAME}" |
| | | docker plugin rm "${NAME}" |
| | | sudo chmod 755 rootfs rootfs/usr/src/app/.local && sudo chmod -R o=g rootfs/usr/src |
| | | for VERSION in ${VERSIONS}; do |
| | | sudo docker plugin create "${NAME}:${VERSION}" . |
| | | done |
| | | sudo du -hs rootfs |
| | | for VERSION in ${VERSIONS}; do |
| | | docker plugin enable "${NAME}:${VERSION}" || exit 1 |
| | | break |
| | | done |
| | | docker plugin disable "${NAME}" || true |
| | | docker plugin rm "${NAME}" || true |
| | | sudo chmod 755 rootfs && sudo chmod -R o=g rootfs/usr/src |
| | | if [ `echo ${VERSIONS} | wc -w` -gt 1 ]; then |
| | | for VERSION in ${VERSIONS}; do |
| | | sudo docker plugin create "${NAME}:${VERSION}" . |
| | | docker plugin push "${NAME}:${VERSION}" |
| | | docker plugin rm "${NAME}:${VERSION}" |
| | | done |
| | | else |
| | | sudo docker plugin create "${NAME}:${VERSIONS}" . |
| | | docker plugin enable "${NAME}:${VERSIONS}" |
| | | fi |
| | |
| | | |
| | | import logging |
| | | import os |
| | | import signal |
| | | import sys |
| | | |
| | | import docker_plugin_api.Plugin |
| | | import flask |
| | |
| | | if os.environ.get('ENVIRONMENT', 'dev') == 'dev': |
| | | app.run(debug=True) |
| | | else: |
| | | signal.signal(signal.SIGTERM, lambda: sys.exit(0)) |
| | | waitress.serve(app, unix_socket='/run/docker/plugins/pyveth.sock', threads=1) |
| | |
| | | #!/bin/sh |
| | | #!/bin/bash |
| | | |
| | | set -e |
| | | set -e -x |
| | | |
| | | NAME=${NAME:-jacekkow/pyveth} |
| | | VERSION=${VERSION:-latest} |
| | | |
| | | PLUGIN="${NAME}:${VERSION}" |
| | | |
| | | docker network rm test1 || true |
| | | docker network rm test2 || true |
| | | |
| | | docker plugin install jacekkow/pyipam:latest || true |
| | | |
| | | docker network create \ |
| | |
| | | test1 |
| | | |
| | | ADDRESSES=$(docker run --rm --network test1 \ |
| | | debian \ |
| | | /bin/ip addr show |
| | | alpine \ |
| | | /sbin/ip addr show |
| | | ) |
| | | echo "${ADDRESSES}" | grep 192.168.255.129/24 |
| | | echo "${ADDRESSES}" | grep 2001:db8:aaaa:bbbb::1/32 |
| | | if ! echo "${ADDRESSES}" | grep 192.168.255.129/24; then |
| | | echo "ERROR: invalid IPv4 address assigned" |
| | | exit 1 |
| | | fi |
| | | if ! echo "${ADDRESSES}" | grep 2001:db8:aaaa:bbbb::1/32; then |
| | | echo "ERROR: invalid IPv6 address assigned" |
| | | exit 1 |
| | | fi |
| | | |
| | | |
| | | ADDRESSES=$(docker run --rm --network test1 \ |
| | | --ip 192.168.255.25 --ip6 2001:db8:dddd:eeee:ffff:1:2:3 \ |
| | | debian \ |
| | | /bin/ip addr show |
| | | alpine \ |
| | | /sbin/ip addr show |
| | | ) |
| | | echo "${ADDRESSES}" | grep 192.168.255.25/24 |
| | | echo "${ADDRESSES}" | grep 2001:db8:dddd:eeee:ffff:1:2:3/32 |
| | | if ! echo "${ADDRESSES}" | grep 192.168.255.25/24; then |
| | | echo "ERROR: invalid IPv4 address assigned" |
| | | exit 1 |
| | | fi |
| | | if ! echo "${ADDRESSES}" | grep 2001:db8:dddd:eeee:ffff:1:2:3/32; then |
| | | echo "ERROR: invalid IPv6 address assigned" |
| | | exit 1 |
| | | fi |
| | | |
| | | docker network rm test1 |
| | | |
| | | |
| | | docker network create \ |
| | | --internal \ |
| | | --driver "${PLUGIN}" \ |
| | | --ipam-driver jacekkow/pyipam:latest \ |
| | | --ipv6 \ |
| | |
| | | test2 |
| | | |
| | | ROUTES=$(docker run --rm --network test2 \ |
| | | debian \ |
| | | /bin/ip route show |
| | | alpine \ |
| | | /sbin/ip route show |
| | | ) |
| | | echo "${ROUTES}" | grep 192.168.255.254 |
| | | if ! echo "${ROUTES}" | grep 192.168.255.254; then |
| | | echo "ERROR: invalid IPv4 route" |
| | | exit 1 |
| | | fi |
| | | |
| | | ROUTES=$(docker run --rm --network test2 \ |
| | | debian \ |
| | | /bin/ip -6 route show |
| | | alpine \ |
| | | /sbin/ip -6 route show |
| | | ) |
| | | echo "${ROUTES}" | grep 2001:db8:ffff:ffff:ffff:ffff:ffff:ffff |
| | | if ! echo "${ROUTES}" | grep 2001:db8:ffff:ffff:ffff:ffff:ffff:ffff; then |
| | | echo "ERROR: invalid IPv6 route" |
| | | exit 1 |
| | | fi |
| | | |
| | | docker network rm test2 |