diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..a142890 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,42 @@ +FROM ubuntu:22.04 + +RUN apt update && \ + apt install -y --no-install-recommends --no-install-suggests \ + netcat-traditional ca-certificates curl gnupg git podman fuse-overlayfs iproute2 + +# Node +ARG NODE_MAJOR=20 +RUN curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg && \ + echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list && \ + apt update && apt install -y nodejs + +# kubectl +RUN curl -LO https://storage.googleapis.com/kubernetes-release/release/`curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt`/bin/linux/amd64/kubectl && \ + chmod +x ./kubectl && \ + mv ./kubectl /usr/bin/kubectl + +# laconic-so +RUN curl -LO https://github.com/cerc-io/stack-orchestrator/releases/latest/download/laconic-so && \ + chmod +x ./laconic-so && \ + mv ./laconic-so /usr/bin/laconic-so + +# laconic-registry-cli +RUN npm config set @cerc-io:registry https://git.vdb.to/api/packages/cerc-io/npm/ && \ + npm install -g @cerc-io/laconic-registry-cli && \ + npm install -g yarn + +# symlink podman to docker +RUN ln -s $(which podman) $(dirname `which podman`)/docker + +RUN mkdir -p /srv/containers/podman + +COPY storage.conf /etc/containers + +RUN mkdir -p /app + +COPY . /app/ +WORKDIR /app/ +RUN rm -rf node_modules && yarn && yarn clean && yarn build:release + +COPY run.sh . +CMD ["./run.sh"] diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..c7c524e --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,14 @@ + +services: + server: + image: cerc/webapp-deployer-backend:local + restart: always + volumes: + - containers:/srv/containers/podman + - config:/etc/config:ro + ports: + - 9555 + +volumes: + config: + containers: diff --git a/run.sh b/run.sh new file mode 100755 index 0000000..1d5e3ab --- /dev/null +++ b/run.sh @@ -0,0 +1,89 @@ +#!/bin/bash + +if [ -z "$DEPLOYMENT_DNS_SUFFIX" ]; then + echo "DEPLOYMENT_DNS_SUFFIX is required." + exit 2 +fi + +if [ -z "$DEPLOYMENT_RECORD_NAMESPACE" ]; then + echo "DEPLOYMENT_RECORD_NAMESPACE is required." + exit 2 +fi + +if [ -z "$IMAGE_REGISTRY" ]; then + echo "IMAGE_REGISTRY is required." + exit 2 +fi + +if [ ! -f "/etc/config/laconic.yml" ]; then + echo "/etc/config/laconic.yml is required." + exit 2 +fi + +if [ ! -f "/etc/config/kube.yml" ]; then + echo "/etc/config/kube.yml is required." + exit 2 +fi + +if [ ! -z "$IMAGE_REGISTRY_CREDS" ]; then + docker login --password "$IMAGE_REGISTRY_CREDS" --username ${IMAGE_REGISTRY_USER:-ANY} $IMAGE_REGISTRY +fi + +function is_privileged { + ip link add dummy0 type dummy >/dev/null + if [[ $? -eq 0 ]]; then + echo "true" + ip link delete dummy0 >/dev/null + else + echo "false" + fi +} + +if [[ "true" == "`is_privileged`" ]]; then + echo "Using 'overlay' storage driver." +else + echo "Using 'vfs' storage driver." + sed -i 's/"overlay"/"vfs"/g' /etc/containers/storage.conf +fi + +if [ ! -d "/srv/deployments/webapps" ]; then + mkdir -p /srv/deployments/webapps +fi + +if [ "$CLEAN_STATE" == "true" ]; then + echo "Removing existing state..." + rm -f /srv/deployments//webapps/*.state +fi + +echo "Starting API" +cd /app/ +yarn start & + +while true; do + echo "==============================================================" + + echo "########### UNDEPLOY ############" + laconic-so undeploy-webapp-from-registry \ + --laconic-config /etc/config/laconic.yml \ + --deployment-parent-dir /srv/deployments/webapps \ + --delete-names \ + --delete-volumes \ + --state-file /srv/deployments/webapps/autoremove.state \ + --discover + + echo "############ DEPLOY #############" + laconic-so deploy-webapp-from-registry \ + --kube-config /etc/config/kube.yml \ + --laconic-config /etc/config/laconic.yml \ + --image-registry ${IMAGE_REGISTRY} \ + --deployment-parent-dir /srv/deployments/webapps \ + --dns-suffix ${DEPLOYMENT_DNS_SUFFIX} \ + --record-namespace-dns crn://${DEPLOYMENT_RECORD_NAMESPACE}/dns \ + --record-namespace-deployments crn://${DEPLOYMENT_RECORD_NAMESPACE}/deployments \ + --state-file /srv/deployments/webapps/autodeploy.state \ + --discover + + # Cleanup any build leftovers + podman system prune --all --force + sleep 15 +done diff --git a/src/config.ts b/src/config.ts index d69f201..7d6d6be 100644 --- a/src/config.ts +++ b/src/config.ts @@ -12,8 +12,8 @@ const loadConfigFile = (configFilePath: string): any => { export const Config = { LISTEN_PORT: parseInt(process.env.LISTEN_PORT || '9555'), LISTEN_ADDR: process.env.LISTEN_ADDR || '0.0.0.0', - LACONIC_CONFIG: process.env.LACONIC_CONFIG || `${process.env.HOME}/.laconic/config.yml`, - DEPLOYER_STATE: process.env.DEPLOYER_STATE + LACONIC_CONFIG: process.env.LACONIC_CONFIG || '/etc/config/laconic.yml', + DEPLOYER_STATE: process.env.DEPLOYER_STATE || '/srv/deployments/webapps/autodeploy.state' }; diff --git a/storage.conf b/storage.conf new file mode 100644 index 0000000..7effdbc --- /dev/null +++ b/storage.conf @@ -0,0 +1,6 @@ +[storage] +driver = "overlay" +runroot = "/srv/containers/podman/run" +graphroot = "/srv/containers/podman/storage" +[storage.options.overlay] +mount_program = "/usr/bin/fuse-overlayfs"