├── ssh-encryption ├── example │ ├── test.txt │ └── docker-compose.yml ├── info.json ├── image │ ├── Dockerfile │ ├── ssh-decrypt │ └── ssh-encrypt ├── push_image.sh └── README.md ├── .gitignore ├── node-app ├── dockerfile-builder │ ├── example │ │ ├── output │ │ │ └── touch.txt │ │ ├── shared │ │ │ ├── capitalize-array │ │ │ │ ├── index.js │ │ │ │ └── package.json │ │ │ └── user-store │ │ │ │ ├── index.js │ │ │ │ └── package.json │ │ ├── app │ │ │ ├── index.js │ │ │ └── package.json │ │ └── docker-compose.yml │ ├── code │ │ ├── app │ │ │ ├── template │ │ │ ├── package.json │ │ │ ├── getCopyCmd.js │ │ │ ├── getCopySharedCmd.js │ │ │ └── index.js │ │ └── dockerfile │ ├── templates │ │ └── docker-compose.yml │ └── README.md ├── base-image │ ├── example2 │ │ ├── dockerfile │ │ ├── docker-compose.yml │ │ └── app │ │ │ ├── package.json │ │ │ └── index.js │ ├── example │ │ ├── shared │ │ │ ├── capitalize-array │ │ │ │ ├── index.js │ │ │ │ └── package.json │ │ │ └── user-store │ │ │ │ ├── index.js │ │ │ │ └── package.json │ │ ├── dockerfile │ │ ├── dockerfile-slim │ │ └── app │ │ │ ├── index.js │ │ │ └── package.json │ ├── example3 │ │ ├── shared │ │ │ ├── array │ │ │ │ ├── capitalize-array │ │ │ │ │ ├── index.js │ │ │ │ │ └── package.json │ │ │ │ └── sort-array │ │ │ │ │ ├── index.js │ │ │ │ │ └── package.json │ │ │ └── user-store │ │ │ │ ├── index.js │ │ │ │ └── package.json │ │ ├── app │ │ │ ├── index.js │ │ │ └── package.json │ │ └── dockerfile │ ├── example5 │ │ ├── dockerfile │ │ ├── dockerfile-slim │ │ ├── shared │ │ │ ├── package.json │ │ │ └── index.js │ │ └── app │ │ │ ├── package.json │ │ │ └── test │ │ │ └── index.js │ ├── example4 │ │ ├── shared │ │ │ ├── module1 │ │ │ │ ├── index.js │ │ │ │ └── package.json │ │ │ └── module2 │ │ │ │ ├── index.js │ │ │ │ └── package.json │ │ ├── app │ │ │ ├── index.js │ │ │ └── package.json │ │ └── dockerfile │ ├── code │ │ ├── finalize.sh │ │ ├── dockerfile │ │ ├── dockerfile-slim │ │ └── resolve_dependencies.js │ ├── templates │ │ ├── dockerfile-template │ │ └── dockerfile-template-slim │ └── README.md ├── image-builder │ ├── code │ │ ├── app │ │ │ ├── template │ │ │ ├── package.json │ │ │ ├── compileDependencies.js │ │ │ ├── wgetDirCmd.js │ │ │ └── index.js │ │ ├── server │ │ │ ├── package.json │ │ │ └── index.js │ │ └── dockerfile │ ├── example │ │ ├── shared │ │ │ ├── capitalize-array │ │ │ │ ├── index.js │ │ │ │ └── package.json │ │ │ └── user-store │ │ │ │ ├── index.js │ │ │ │ └── package.json │ │ ├── app │ │ │ ├── index.js │ │ │ └── package.json │ │ ├── docker-compose.yml │ │ └── docker-compose-slim.yml │ ├── example2 │ │ ├── shared │ │ │ ├── package.json │ │ │ └── index.js │ │ ├── app │ │ │ ├── package.json │ │ │ └── test │ │ │ │ └── index.js │ │ ├── docker-compose.yml │ │ └── docker-compose-slim.yml │ ├── templates │ │ └── docker-compose.yml │ └── README.md ├── base-dev-image │ ├── example │ │ ├── shared │ │ │ ├── module1 │ │ │ │ ├── index.js │ │ │ │ └── package.json │ │ │ └── module2 │ │ │ │ ├── index.js │ │ │ │ └── package.json │ │ ├── app │ │ │ ├── index.js │ │ │ └── package.json │ │ └── docker-compose.yml │ ├── code │ │ ├── finalize.sh │ │ ├── dockerfile │ │ └── resolve_dependencies.js │ └── README.md └── README.md ├── headless-factorio-server ├── requirements.txt ├── templates │ ├── server-adminlist.json.j2 │ ├── server-whitelist.json.j2 │ ├── map-gen-settings.json.j2 │ └── server-settings.json.j2 ├── docker-compose.yml ├── Dockerfile ├── code │ ├── game.py │ └── entrypoint.py └── README.md ├── certificate ├── example │ ├── ca-signed-with-password │ │ ├── password.txt │ │ ├── ca-password.txt │ │ └── docker-compose.yml │ ├── self-signed-with-password │ │ ├── password.txt │ │ └── docker-compose.yml │ ├── self-signed │ │ └── docker-compose.yml │ └── ca-signed │ │ └── docker-compose.yml ├── Dockerfile └── test │ └── run.py ├── remote-terraform ├── ansible_scripts │ ├── roles │ │ ├── deploy_scripts │ │ │ ├── files │ │ │ │ └── placeholder │ │ │ └── tasks │ │ │ │ └── main.yml │ │ ├── cleanup_scripts │ │ │ └── tasks │ │ │ │ └── main.yml │ │ ├── terraform_plan │ │ │ └── tasks │ │ │ │ └── main.yml │ │ └── terraform_apply │ │ │ └── tasks │ │ │ └── main.yml │ ├── plan.yml │ └── apply.yml ├── info.json ├── push_image.sh ├── binaries │ ├── plan │ └── apply └── Dockerfile ├── ansible ├── README.md ├── info.json ├── Dockerfile └── push_image.sh ├── automated-tests ├── run.sh ├── user-store │ ├── node-0.10.df │ ├── node-4.1.df │ ├── build.sh │ └── run.sh ├── user-properties │ ├── node-0.10.df │ ├── node-4.1.df │ ├── run.sh │ └── build.sh ├── express-access-control │ ├── node-0.10.df │ ├── node-4.1.df │ ├── run.sh │ └── build.sh ├── node-4.1-base.df ├── node-0.10-base.df ├── build.sh └── build-base.sh ├── pulsar-orchestration ├── cleanup.sh ├── README.md ├── zookeeper-conf │ └── zoo.cfg ├── configure_zookeeper.sh ├── launch.sh ├── docker-compose.yml └── bookkeeper-conf │ └── bookkeeper.conf ├── react-build ├── code │ ├── dockerfile-onbuild │ ├── dockerfile-onbuild-slim │ ├── dockerfile │ ├── dockerfile-slim │ └── app │ │ ├── package.json │ │ └── index.js ├── example-onbuild │ ├── dockerfile │ ├── docker-compose.yml │ ├── app │ │ └── javascript │ │ │ ├── header.jsx │ │ │ ├── index.jsx │ │ │ ├── draw-section.jsx │ │ │ ├── registration-feedback.jsx │ │ │ ├── draw-feedback.jsx │ │ │ ├── register-section.jsx │ │ │ └── app.jsx │ ├── build.json │ └── lib │ │ ├── draw.js │ │ ├── participants.js │ │ └── pot.js ├── example │ ├── docker-compose.yml │ ├── app │ │ └── javascript │ │ │ ├── header.jsx │ │ │ ├── index.jsx │ │ │ ├── draw-section.jsx │ │ │ ├── registration-feedback.jsx │ │ │ ├── draw-feedback.jsx │ │ │ ├── register-section.jsx │ │ │ └── app.jsx │ ├── build.json │ └── lib │ │ ├── draw.js │ │ ├── participants.js │ │ └── pot.js └── README.md ├── electron-app ├── app │ ├── package.json │ ├── index.html │ └── main.js ├── docker-compose.yml ├── dockerfile ├── entryScript.sh └── README.md ├── cfssl ├── example │ ├── ca-csr.json │ ├── client.json │ └── ca-config.json ├── amd64 │ └── Dockerfile ├── arm64 │ └── Dockerfile └── README.md ├── chrony ├── Dockerfile └── README.md ├── pyspark ├── run.sh ├── README.md └── Dockerfile ├── chrome ├── dockerfile ├── entryScript.sh ├── docker-compose.yml └── README.md ├── hapi-service ├── hello-world │ ├── dockerfile │ ├── package.json │ └── index.js └── README.md ├── jedit ├── entryScript.sh ├── docker-compose.yml ├── dockerfile └── README.md ├── network-setup ├── image │ ├── dns.conf.j2 │ ├── zonefile.j2 │ ├── Dockerfile │ └── dhcp.conf.j2 ├── docker-compose.yml ├── conf └── README.md ├── isc-dhcp-server ├── example │ ├── docker-compose.yml │ └── dhcpd.conf ├── entrypoint.sh ├── Dockerfile-amd64 ├── Dockerfile-arm64 └── README.md ├── .github └── workflows │ ├── build_ansible.yml │ ├── build_ssh_encryption.yml │ ├── build_remote_terraform.yml │ ├── publish_ansible.yml │ ├── publish_ssh_encryption.yml │ └── publish_remote_terraform.yml ├── sbt ├── Dockerfile └── README.md └── License.txt /ssh-encryption/example/test.txt: -------------------------------------------------------------------------------- 1 | Hello world! -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | #editor generated backup files 2 | *~ 3 | -------------------------------------------------------------------------------- /node-app/dockerfile-builder/example/output/touch.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /headless-factorio-server/requirements.txt: -------------------------------------------------------------------------------- 1 | jinja2 == 2.11.1 -------------------------------------------------------------------------------- /certificate/example/ca-signed-with-password/password.txt: -------------------------------------------------------------------------------- 1 | foobar 2 | -------------------------------------------------------------------------------- /certificate/example/ca-signed-with-password/ca-password.txt: -------------------------------------------------------------------------------- 1 | cafoobar 2 | -------------------------------------------------------------------------------- /certificate/example/self-signed-with-password/password.txt: -------------------------------------------------------------------------------- 1 | foobar 2 | -------------------------------------------------------------------------------- /remote-terraform/ansible_scripts/roles/deploy_scripts/files/placeholder: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ansible/README.md: -------------------------------------------------------------------------------- 1 | # About 2 | 3 | Simple image to troubleshoot ansible playbooks locally -------------------------------------------------------------------------------- /automated-tests/run.sh: -------------------------------------------------------------------------------- 1 | for dir in */ ; do 2 | (cd "$dir"; ./run.sh); 3 | done 4 | -------------------------------------------------------------------------------- /ansible/info.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0", 3 | "image_repo": "magnitus/ansible" 4 | } -------------------------------------------------------------------------------- /headless-factorio-server/templates/server-adminlist.json.j2: -------------------------------------------------------------------------------- 1 | [ 2 | {{ players|join(', ') }} 3 | ] -------------------------------------------------------------------------------- /headless-factorio-server/templates/server-whitelist.json.j2: -------------------------------------------------------------------------------- 1 | [ 2 | {{ players|join(', ') }} 3 | ] -------------------------------------------------------------------------------- /pulsar-orchestration/cleanup.sh: -------------------------------------------------------------------------------- 1 | docker-compose down; 2 | rm -r zookeeper; 3 | sudo rm -r bookie; -------------------------------------------------------------------------------- /react-build/code/dockerfile-onbuild: -------------------------------------------------------------------------------- 1 | FROM magnitus/node-app:4 2 | 3 | COPY "app/*" ${APP_DIR}/ 4 | -------------------------------------------------------------------------------- /ansible/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.9-slim-bullseye 2 | 3 | RUN python3 -m pip install ansible-core==2.12.3 -------------------------------------------------------------------------------- /react-build/code/dockerfile-onbuild-slim: -------------------------------------------------------------------------------- 1 | FROM magnitus/node-app:4-slim 2 | 3 | COPY "app/*" ${APP_DIR}/ 4 | -------------------------------------------------------------------------------- /ssh-encryption/info.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0", 3 | "image_repo": "magnitus/ssh-encryption" 4 | } -------------------------------------------------------------------------------- /remote-terraform/info.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0", 3 | "image_repo": "magnitus/remote-terraform" 4 | } -------------------------------------------------------------------------------- /electron-app/app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name" : "hello-world", 3 | "version" : "0.1.0", 4 | "main" : "main.js" 5 | } 6 | -------------------------------------------------------------------------------- /cfssl/example/ca-csr.json: -------------------------------------------------------------------------------- 1 | { 2 | "CN": "etcd", 3 | "key": { 4 | "algo": "rsa", 5 | "size": 2048 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /chrony/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM debian:stretch 2 | 3 | RUN apt-get update && apt-get install -y chrony 4 | 5 | CMD ["/usr/sbin/chronyd", "-d"] -------------------------------------------------------------------------------- /automated-tests/user-store/node-0.10.df: -------------------------------------------------------------------------------- 1 | FROM magnitus/automated-tests:node-0.10-base 2 | ENV PROJECT="UserStore" 3 | RUN /opt/build-base.sh 4 | -------------------------------------------------------------------------------- /automated-tests/user-store/node-4.1.df: -------------------------------------------------------------------------------- 1 | FROM magnitus/automated-tests:node-4.1-base 2 | ENV PROJECT="UserStore" 3 | RUN /opt/build-base.sh 4 | -------------------------------------------------------------------------------- /cfssl/example/client.json: -------------------------------------------------------------------------------- 1 | { 2 | "CN": "client", 3 | "key": { 4 | "algo": "ecdsa", 5 | "size": 256 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /react-build/example-onbuild/dockerfile: -------------------------------------------------------------------------------- 1 | FROM magnitus/react-compiler:onbuild 2 | 3 | ENV UID="1000" 4 | 5 | RUN finalize.sh 6 | 7 | USER $UID 8 | -------------------------------------------------------------------------------- /automated-tests/user-properties/node-0.10.df: -------------------------------------------------------------------------------- 1 | FROM magnitus/automated-tests:node-0.10-base 2 | ENV PROJECT="UserProperties" 3 | RUN /opt/build-base.sh 4 | -------------------------------------------------------------------------------- /automated-tests/user-properties/node-4.1.df: -------------------------------------------------------------------------------- 1 | FROM magnitus/automated-tests:node-4.1-base 2 | ENV PROJECT="UserProperties" 3 | RUN /opt/build-base.sh 4 | -------------------------------------------------------------------------------- /automated-tests/express-access-control/node-0.10.df: -------------------------------------------------------------------------------- 1 | FROM magnitus/automated-tests:node-0.10-base 2 | ENV PROJECT="ExpressAccessControl" 3 | RUN /opt/build-base.sh 4 | -------------------------------------------------------------------------------- /automated-tests/express-access-control/node-4.1.df: -------------------------------------------------------------------------------- 1 | FROM magnitus/automated-tests:node-4.1-base 2 | ENV PROJECT="ExpressAccessControl" 3 | RUN /opt/build-base.sh 4 | -------------------------------------------------------------------------------- /pyspark/run.sh: -------------------------------------------------------------------------------- 1 | docker build -t pyspark-jupyter-notebook:latest .; 2 | docker run -d --rm -p "8888:8888" --name pyspark-jupyter-notebook pyspark-jupyter-notebook:latest; -------------------------------------------------------------------------------- /react-build/code/dockerfile: -------------------------------------------------------------------------------- 1 | FROM magnitus/node-app:4 2 | 3 | COPY "app/*" ${APP_DIR}/ 4 | 5 | ENV UID="0" 6 | 7 | RUN finalize.sh 8 | 9 | USER $UID 10 | -------------------------------------------------------------------------------- /react-build/code/dockerfile-slim: -------------------------------------------------------------------------------- 1 | FROM magnitus/node-app:4-slim 2 | 3 | COPY "app/*" ${APP_DIR}/ 4 | 5 | ENV UID="0" 6 | 7 | RUN finalize.sh 8 | 9 | USER $UID 10 | -------------------------------------------------------------------------------- /node-app/base-image/example2/dockerfile: -------------------------------------------------------------------------------- 1 | FROM magnitus/node-app:4 2 | 3 | ENV UID="1000" 4 | 5 | COPY "app/* ${APP_DIR}/ 6 | 7 | RUN finalize.sh 8 | 9 | USER $UID 10 | -------------------------------------------------------------------------------- /node-app/image-builder/code/app/template: -------------------------------------------------------------------------------- 1 | FROM {{SOURCE}} 2 | 3 | ENV UID="{{UID}}" 4 | {{NPM_COMMAND}} 5 | 6 | {{COPY_ALL}} 7 | 8 | RUN finalize.sh 9 | 10 | USER $UID 11 | -------------------------------------------------------------------------------- /automated-tests/user-properties/run.sh: -------------------------------------------------------------------------------- 1 | docker run -it --rm magnitus/automated-tests:0.10-node-user-properties; 2 | docker run -it --rm magnitus/automated-tests:4.1-node-user-properties; 3 | -------------------------------------------------------------------------------- /ssh-encryption/image/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:20.04 2 | 3 | RUN apt-get update && apt-get install -y openssl openssh-client 4 | 5 | COPY ssh-decrypt ssh-encrypt /usr/bin/ 6 | 7 | WORKDIR /opt -------------------------------------------------------------------------------- /node-app/base-image/example2/docker-compose.yml: -------------------------------------------------------------------------------- 1 | app: 2 | container_name: node-app-hapi-example 3 | image: magnitus/node-app:example-hapi 4 | restart: always 5 | ports: 6 | - "8080:8080" -------------------------------------------------------------------------------- /automated-tests/user-store/build.sh: -------------------------------------------------------------------------------- 1 | docker build -t magnitus/automated-tests:0.10-node-user-store -f node-0.10.df .; 2 | docker build -t magnitus/automated-tests:4.1-node-user-store -f node-4.1.df .; 3 | -------------------------------------------------------------------------------- /chrome/dockerfile: -------------------------------------------------------------------------------- 1 | FROM jess/chrome:stable 2 | COPY ["./entryScript.sh", "/opt/entryScript.sh"] 3 | RUN chmod +x /opt/entryScript.sh 4 | ENTRYPOINT ["/bin/bash", "/opt/entryScript.sh"] 5 | CMD [ "" ] 6 | -------------------------------------------------------------------------------- /node-app/dockerfile-builder/code/app/template: -------------------------------------------------------------------------------- 1 | FROM magnitus/node-app:4 2 | 3 | ENV UID="{{UID}}" 4 | 5 | {{COPY_APP}} 6 | 7 | {{COPY_SHARED}} 8 | 9 | RUN finalize.sh 10 | 11 | USER $UID 12 | -------------------------------------------------------------------------------- /remote-terraform/ansible_scripts/roles/cleanup_scripts/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - name: Remove terraform configuration from bastion 2 | file: 3 | path: "{{ remote_terraform_config_dir }}" 4 | state: absent -------------------------------------------------------------------------------- /automated-tests/express-access-control/run.sh: -------------------------------------------------------------------------------- 1 | docker run -it --rm magnitus/automated-tests:0.10-node-express-access-control; 2 | docker run -it --rm magnitus/automated-tests:4.1-node-express-access-control; 3 | -------------------------------------------------------------------------------- /remote-terraform/ansible_scripts/roles/deploy_scripts/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - name: Copy terraform configuration to bastion 2 | copy: 3 | src: "terraform/" 4 | dest: "{{ remote_terraform_config_dir }}/" 5 | -------------------------------------------------------------------------------- /automated-tests/user-properties/build.sh: -------------------------------------------------------------------------------- 1 | docker build -t magnitus/automated-tests:0.10-node-user-properties -f node-0.10.df .; 2 | docker build -t magnitus/automated-tests:4.1-node-user-properties -f node-4.1.df .; 3 | -------------------------------------------------------------------------------- /cfssl/amd64/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.14 2 | 3 | RUN go get -u github.com/cloudflare/cfssl/cmd/cfssl && go get -u github.com/cloudflare/cfssl/cmd/cfssljson 4 | 5 | WORKDIR /opt 6 | 7 | ENTRYPOINT [""] 8 | CMD ["sh"] -------------------------------------------------------------------------------- /cfssl/arm64/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM arm64v8/golang:1.14 2 | 3 | RUN go get -u github.com/cloudflare/cfssl/cmd/cfssl && go get -u github.com/cloudflare/cfssl/cmd/cfssljson 4 | 5 | WORKDIR /opt 6 | 7 | ENTRYPOINT [""] 8 | CMD ["sh"] -------------------------------------------------------------------------------- /hapi-service/hello-world/dockerfile: -------------------------------------------------------------------------------- 1 | FROM magnitus/node-app:4-slim 2 | 3 | ENV UID="1000" 4 | 5 | COPY ["index.js", "package.json", "${APP_DIR}/"] 6 | 7 | RUN finalize.sh 8 | 9 | USER $UID 10 | 11 | EXPOSE 8080 12 | -------------------------------------------------------------------------------- /node-app/base-image/example/shared/capitalize-array/index.js: -------------------------------------------------------------------------------- 1 | module.exports = function(array) { 2 | return array.map(function(value) { 3 | return value.charAt(0).toUpperCase() + value.slice(1); 4 | }); 5 | } 6 | 7 | -------------------------------------------------------------------------------- /ansible/push_image.sh: -------------------------------------------------------------------------------- 1 | export IMAGE_REPO=$(cat ./info.json | jq -r ".image_repo") 2 | export VERSION=$(cat ./info.json | jq -r ".version") 3 | export IMAGE=$IMAGE_REPO:$VERSION 4 | 5 | docker build -t $IMAGE . 6 | 7 | docker push $IMAGE -------------------------------------------------------------------------------- /jedit/entryScript.sh: -------------------------------------------------------------------------------- 1 | echo "${_USER}:x:${_UID}:${_UID}:${_USER},,,:/home/${_USER}:/bin/bash" >> /etc/passwd && \ 2 | echo "${_USER}:x:${_UID}:" >> /etc/group && \ 3 | chown $_UID:$_UID -R /home/$_USER && \ 4 | su - $_USER -c "jedit" 5 | -------------------------------------------------------------------------------- /node-app/image-builder/example/shared/capitalize-array/index.js: -------------------------------------------------------------------------------- 1 | module.exports = function(array) { 2 | return array.map(function(value) { 3 | return value.charAt(0).toUpperCase() + value.slice(1); 4 | }); 5 | } 6 | 7 | -------------------------------------------------------------------------------- /automated-tests/express-access-control/build.sh: -------------------------------------------------------------------------------- 1 | docker build -t magnitus/automated-tests:0.10-node-express-access-control -f node-0.10.df .; 2 | docker build -t magnitus/automated-tests:4.1-node-express-access-control -f node-4.1.df .; 3 | -------------------------------------------------------------------------------- /automated-tests/node-4.1-base.df: -------------------------------------------------------------------------------- 1 | FROM node:4.1 2 | RUN apt-get update 3 | RUN apt-get install unzip 4 | COPY ["./build-base.sh", "/opt/build-base.sh"] 5 | RUN chmod +x /opt/build-base.sh 6 | ENTRYPOINT ["/bin/bash"] 7 | CMD ["runtest.sh"] 8 | -------------------------------------------------------------------------------- /node-app/base-image/example3/shared/array/capitalize-array/index.js: -------------------------------------------------------------------------------- 1 | module.exports = function(array) { 2 | return array.map(function(value) { 3 | return value.charAt(0).toUpperCase() + value.slice(1); 4 | }); 5 | } 6 | 7 | -------------------------------------------------------------------------------- /node-app/dockerfile-builder/example/shared/capitalize-array/index.js: -------------------------------------------------------------------------------- 1 | module.exports = function(array) { 2 | return array.map(function(value) { 3 | return value.charAt(0).toUpperCase() + value.slice(1); 4 | }); 5 | } 6 | 7 | -------------------------------------------------------------------------------- /automated-tests/node-0.10-base.df: -------------------------------------------------------------------------------- 1 | FROM node:0.10 2 | RUN apt-get update 3 | RUN apt-get install unzip 4 | COPY ["./build-base.sh", "/opt/build-base.sh"] 5 | RUN chmod +x /opt/build-base.sh 6 | ENTRYPOINT ["/bin/bash"] 7 | CMD ["runtest.sh"] 8 | -------------------------------------------------------------------------------- /remote-terraform/push_image.sh: -------------------------------------------------------------------------------- 1 | export IMAGE_REPO=$(cat ./info.json | jq -r ".image_repo") 2 | export VERSION=$(cat ./info.json | jq -r ".version") 3 | export IMAGE=$IMAGE_REPO:$VERSION 4 | 5 | docker build -t $IMAGE . 6 | 7 | docker push $IMAGE -------------------------------------------------------------------------------- /automated-tests/build.sh: -------------------------------------------------------------------------------- 1 | docker build -t magnitus/automated-tests:node-0.10-base -f node-0.10-base.df .; 2 | docker build -t magnitus/automated-tests:node-4.1-base -f node-4.1-base.df .; 3 | for dir in */ ; do 4 | (cd "$dir"; ./build.sh); 5 | done 6 | -------------------------------------------------------------------------------- /node-app/base-image/example/shared/user-store/index.js: -------------------------------------------------------------------------------- 1 | const CapitalizeArray = require('capitalize-array'); 2 | 3 | module.exports = { 4 | 'getUsers': function() { 5 | return CapitalizeArray(['sally','craigs','chris','tom']); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /node-app/image-builder/example/shared/user-store/index.js: -------------------------------------------------------------------------------- 1 | const CapitalizeArray = require('capitalize-array'); 2 | 3 | module.exports = { 4 | 'getUsers': function() { 5 | return CapitalizeArray(['sally','craigs','chris','tom']); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /node-app/dockerfile-builder/example/shared/user-store/index.js: -------------------------------------------------------------------------------- 1 | const CapitalizeArray = require('capitalize-array'); 2 | 3 | module.exports = { 4 | 'getUsers': function() { 5 | return CapitalizeArray(['sally','craigs','chris','tom']); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /chrony/README.md: -------------------------------------------------------------------------------- 1 | # Purpose 2 | 3 | Pretty simple image to run Chrony in a container. 4 | 5 | A configuration file needs to be mapped at **/etc/chrony.conf** in the container and you probably want to give the container the **CAP_SYS_TIME** permission as well. 6 | 7 | -------------------------------------------------------------------------------- /electron-app/app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Hello World! 6 | 7 | 8 |

Hello world from example app!

9 | 10 | 11 | -------------------------------------------------------------------------------- /hapi-service/README.md: -------------------------------------------------------------------------------- 1 | # hapi-service 2 | 3 | Per-container standalone hapi services that can be bolted to an app behind a reverse-proxy. 4 | 5 | Atm, there is only an hello-world service to test the latest iteration of the letsencrypt reverse-proxy I implemented. 6 | -------------------------------------------------------------------------------- /network-setup/image/dns.conf.j2: -------------------------------------------------------------------------------- 1 | {% for network in networks %} 2 | {{ network.domain }} { 3 | file /etc/network-setup/zonefile.{{ network.domain }} 4 | log 5 | } 6 | {% endfor %} 7 | 8 | . { 9 | forward . {{ fallback_dns_server }} 10 | log 11 | } -------------------------------------------------------------------------------- /ssh-encryption/push_image.sh: -------------------------------------------------------------------------------- 1 | export IMAGE_REPO=$(cat ./info.json | jq -r ".image_repo") 2 | export VERSION=$(cat ./info.json | jq -r ".version") 3 | export IMAGE=$IMAGE_REPO:$VERSION 4 | 5 | ( 6 | cd image; 7 | docker build -t $IMAGE .; 8 | docker push $IMAGE; 9 | ) -------------------------------------------------------------------------------- /node-app/base-image/example5/dockerfile: -------------------------------------------------------------------------------- 1 | FROM magnitus/node-app:4 2 | 3 | ENV UID="1000" 4 | ENV NPM_COMMAND test 5 | 6 | COPY "app/*" ${APP_DIR}/ 7 | COPY "app/test/* ${APP_DIR}/test/ 8 | COPY shared/* ${SHARED_DIR}/ 9 | 10 | RUN finalize.sh 11 | 12 | USER $UID 13 | -------------------------------------------------------------------------------- /node-app/base-dev-image/example/shared/module1/index.js: -------------------------------------------------------------------------------- 1 | const Xregexp = require('xregexp'); 2 | 3 | module.exports = function() { 4 | console.log('console log from module1, xregexp version should be 3.1.1'); 5 | console.log('xregexp version is: '+Xregexp.version); 6 | } 7 | 8 | -------------------------------------------------------------------------------- /node-app/base-image/example4/shared/module1/index.js: -------------------------------------------------------------------------------- 1 | const Xregexp = require('xregexp'); 2 | 3 | module.exports = function() { 4 | console.log('console log from module1, xregexp version should be 3.1.1'); 5 | console.log('xregexp version is: '+Xregexp.version); 6 | } 7 | 8 | -------------------------------------------------------------------------------- /node-app/base-dev-image/example/shared/module2/index.js: -------------------------------------------------------------------------------- 1 | const Xregexp = require('xregexp'); 2 | 3 | module.exports = function() { 4 | console.log('console log from module2, xregexp version should be undefined'); 5 | console.log('xregexp version is: '+Xregexp.version); 6 | } 7 | 8 | -------------------------------------------------------------------------------- /node-app/base-image/example4/shared/module2/index.js: -------------------------------------------------------------------------------- 1 | const Xregexp = require('xregexp'); 2 | 3 | module.exports = function() { 4 | console.log('console log from module2, xregexp version should be undefined'); 5 | console.log('xregexp version is: '+Xregexp.version); 6 | } 7 | 8 | -------------------------------------------------------------------------------- /node-app/base-image/example5/dockerfile-slim: -------------------------------------------------------------------------------- 1 | FROM magnitus/node-app:4-slim 2 | 3 | ENV UID="1000" 4 | ENV NPM_COMMAND test 5 | 6 | COPY "app/*" ${APP_DIR}/ 7 | COPY "app/test/* ${APP_DIR}/test/ 8 | COPY shared/* ${SHARED_DIR}/ 9 | 10 | RUN finalize.sh 11 | 12 | USER $UID 13 | -------------------------------------------------------------------------------- /node-app/base-image/example/dockerfile: -------------------------------------------------------------------------------- 1 | FROM magnitus/node-app:4 2 | 3 | ENV UID="1000" 4 | 5 | COPY "app/*" ${APP_DIR}/ 6 | COPY "shared/user-store" ${SHARED_DIR}/user-store 7 | COPY "shared/capitalize-array" ${SHARED_DIR}/capitalize-array 8 | 9 | RUN finalize.sh 10 | 11 | USER $UID 12 | -------------------------------------------------------------------------------- /node-app/base-image/code/finalize.sh: -------------------------------------------------------------------------------- 1 | echo "node-app:x:${UID}:${UID}:node-app,,,:/home/node-app:/bin/bash" >> /etc/passwd; 2 | echo "node-app:x:${UID}:" >> /etc/group; 3 | 4 | /opt/app-setup/resolve_dependencies.js; 5 | 6 | chown -R ${UID}:${UID} /home/node-app; 7 | chown -R ${UID}:${UID} ${SHARED_DIR}; 8 | -------------------------------------------------------------------------------- /node-app/base-image/example/dockerfile-slim: -------------------------------------------------------------------------------- 1 | FROM magnitus/node-app:4-slim 2 | 3 | ENV UID="1000" 4 | 5 | COPY "app/*" ${APP_DIR}/ 6 | COPY "shared/user-store" ${SHARED_DIR}/user-store 7 | COPY "shared/capitalize-array" ${SHARED_DIR}/capitalize-array 8 | 9 | RUN finalize.sh 10 | 11 | USER $UID 12 | -------------------------------------------------------------------------------- /node-app/base-image/example3/shared/user-store/index.js: -------------------------------------------------------------------------------- 1 | const CapitalizeArray = require('capitalize-array'); 2 | const SortArray = require('sort-array'); 3 | 4 | module.exports = { 5 | 'getUsers': function() { 6 | return SortArray(CapitalizeArray(['sally','craigs','chris','tom'])); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /remote-terraform/binaries/plan: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | mkdir -p /opt/bastion_terraform/roles/deploy_scripts/files 4 | cp -r $TERRAFORM_DIR /opt/bastion_terraform/roles/deploy_scripts/files/terraform 5 | ansible-playbook /opt/bastion_terraform/plan.yml --private-key=$PRIVATE_SSH_KEY -u $ANSIBLE_USER -i $INVENTORY -------------------------------------------------------------------------------- /jedit/docker-compose.yml: -------------------------------------------------------------------------------- 1 | jedit: 2 | image: magnitus/jedit:latest 3 | environment: 4 | - DISPLAY=$DISPLAY 5 | - _USER=eric 6 | - _UID=1000 7 | volumes: 8 | - /tmp/.X11-unix:/tmp/.X11-unix 9 | - /home/eric 10 | - /home/eric/Projects:/home/eric/files 11 | -------------------------------------------------------------------------------- /network-setup/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | setup: 4 | image: magnitus/network-setup:latest 5 | volumes: 6 | - "./conf:/opt/conf" 7 | - "/var/run/docker.sock:/var/run/docker.sock" 8 | - "network-config:/etc/network-setup" 9 | 10 | volumes: 11 | network-config: -------------------------------------------------------------------------------- /node-app/base-image/example4/app/index.js: -------------------------------------------------------------------------------- 1 | const Xregexp = require('xregexp'); 2 | const Bluebird = require('bluebird'); 3 | 4 | (require('module1')()); 5 | (require('module2')()); 6 | 7 | console.log('console log from main, xregexp version should be 3.1.1'); 8 | console.log('xregexp version is: '+Xregexp.version); 9 | -------------------------------------------------------------------------------- /remote-terraform/binaries/apply: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | mkdir -p /opt/bastion_terraform/roles/deploy_scripts/files 4 | cp -r $TERRAFORM_DIR /opt/bastion_terraform/roles/deploy_scripts/files/terraform 5 | ansible-playbook /opt/bastion_terraform/apply.yml --private-key=$PRIVATE_SSH_KEY -u $ANSIBLE_USER -i $INVENTORY -------------------------------------------------------------------------------- /electron-app/docker-compose.yml: -------------------------------------------------------------------------------- 1 | electron: 2 | image: magnitus/electron-app:dev-beta 3 | environment: 4 | - DISPLAY=$DISPLAY 5 | - _USER=eric 6 | - _UID=1000 7 | volumes: 8 | - /tmp/.X11-unix:/tmp/.X11-unix 9 | - /home/eric 10 | - ./app:/home/eric/app 11 | -------------------------------------------------------------------------------- /node-app/base-dev-image/example/app/index.js: -------------------------------------------------------------------------------- 1 | const Xregexp = require('xregexp'); 2 | const Bluebird = require('bluebird'); 3 | 4 | (require('module1')()); 5 | (require('module2')()); 6 | 7 | console.log('console log from main, xregexp version should be 3.1.1'); 8 | console.log('xregexp version is: '+Xregexp.version); 9 | -------------------------------------------------------------------------------- /chrome/entryScript.sh: -------------------------------------------------------------------------------- 1 | echo "chrome:x:${_UID}:${_UID}:chrome,,,:/home/chrome:/bin/bash" >> /etc/passwd && \ 2 | echo "chrome:x:${_UID}:" >> /etc/group && \ 3 | chown ${_UID}:${_UID} /home/chrome && \ 4 | chown ${_UID}:${_UID} /data && \ 5 | usermod -a -G audio chrome && \ 6 | su - chrome -c "google-chrome --user-data-dir=/data" 7 | -------------------------------------------------------------------------------- /node-app/base-dev-image/example/docker-compose.yml: -------------------------------------------------------------------------------- 1 | app: 2 | image: magnitus/node-app:4-dev 3 | container_name: node-app-dev-example 4 | environment: 5 | - UID=1000 6 | - NPM_MODULES=bluebird@3;xregexp@3.1.1 7 | volumes: 8 | - ./app:/home/node-app/app 9 | - ./shared:/home/node-app/shared_modules 10 | -------------------------------------------------------------------------------- /node-app/base-image/example4/dockerfile: -------------------------------------------------------------------------------- 1 | FROM magnitus/node-app:4 2 | 3 | ENV UID="1000" 4 | 5 | COPY "app/*" ${APP_DIR}/ 6 | COPY "shared/module1" ${SHARED_DIR}/module1 7 | COPY "shared/module2" ${SHARED_DIR}/module2 8 | 9 | ENV NPM_MODULES="bluebird@3;xregexp@3.1.1" 10 | 11 | RUN finalize.sh 12 | 13 | USER $UID 14 | -------------------------------------------------------------------------------- /isc-dhcp-server/example/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | services: 3 | dhcp-server: 4 | image: magnitus/isc-dhcp-server:latest 5 | restart: always 6 | network_mode: host 7 | environment: 8 | INTERFACE: eth0 9 | volumes: 10 | - ./dhcpd.conf:/opt/dhcp/dhcpd.conf -------------------------------------------------------------------------------- /node-app/base-image/example/app/index.js: -------------------------------------------------------------------------------- 1 | //Sample app that prints all the users in a mock database 2 | //The database entrypoints would be shared modules accross apps 3 | var UserStore = require('user-store'); 4 | 5 | var users = UserStore.getUsers(); 6 | 7 | users.forEach(function(user) { 8 | console.log(user); 9 | }); 10 | -------------------------------------------------------------------------------- /node-app/base-image/example3/app/index.js: -------------------------------------------------------------------------------- 1 | //Sample app that prints all the users in a mock database 2 | //The database entrypoints would be shared modules accross apps 3 | var UserStore = require('user-store'); 4 | 5 | var users = UserStore.getUsers(); 6 | 7 | users.forEach(function(user) { 8 | console.log(user); 9 | }); 10 | -------------------------------------------------------------------------------- /node-app/image-builder/example/app/index.js: -------------------------------------------------------------------------------- 1 | //Sample app that prints all the users in a mock database 2 | //The database entrypoints would be shared modules accross apps 3 | var UserStore = require('user-store'); 4 | 5 | var users = UserStore.getUsers(); 6 | 7 | users.forEach(function(user) { 8 | console.log(user); 9 | }); 10 | -------------------------------------------------------------------------------- /react-build/example-onbuild/docker-compose.yml: -------------------------------------------------------------------------------- 1 | app: 2 | container_name: react-compiler-onbuild-example 3 | build: . 4 | environment: 5 | - BUILD_FILE=/opt/build.json 6 | volumes: 7 | - ./build.json:/opt/build.json 8 | - ./app/javascript:/opt/app/javascript 9 | - ./lib:/opt/lib 10 | - ./app/dist:/opt/dist 11 | -------------------------------------------------------------------------------- /node-app/dockerfile-builder/example/app/index.js: -------------------------------------------------------------------------------- 1 | //Sample app that prints all the users in a mock database 2 | //The database entrypoints would be shared modules accross apps 3 | var UserStore = require('user-store'); 4 | 5 | var users = UserStore.getUsers(); 6 | 7 | users.forEach(function(user) { 8 | console.log(user); 9 | }); 10 | -------------------------------------------------------------------------------- /automated-tests/build-base.sh: -------------------------------------------------------------------------------- 1 | wget --output-document="/opt/master.zip" https://github.com/Magnitus-/$PROJECT/archive/master.zip; 2 | (cd /opt; unzip master.zip); 3 | (cd /opt/"$PROJECT"-master; npm install); 4 | touch /bin/runtest.sh; 5 | echo "(cd /opt/$PROJECT-master; npm test)" > /bin/runtest.sh; 6 | chmod +x /bin/runtest.sh; 7 | rm /opt/master.zip; 8 | -------------------------------------------------------------------------------- /isc-dhcp-server/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | cp $SOURCE_CONF_PATH $CONF_PATH; 4 | touch $LEASE_PATH; 5 | 6 | chown $RUNTIME_USER:$RUNTIME_USER $CONF_PATH; 7 | chown $RUNTIME_USER:$RUNTIME_USER $LEASE_PATH; 8 | 9 | exec /usr/sbin/dhcpd -$IP_VERSION -d -f --no-pid -user $RUNTIME_USER -group $RUNTIME_USER -cf $CONF_PATH -lf $LEASE_PATH $INTERFACE -------------------------------------------------------------------------------- /.github/workflows/build_ansible.yml: -------------------------------------------------------------------------------- 1 | name: Build Ansible Image 2 | 3 | on: 4 | push: 5 | paths: 6 | - 'ansible/**' 7 | 8 | jobs: 9 | publish: 10 | name: Build Image 11 | runs-on: ubuntu-18.04 12 | steps: 13 | - uses: actions/checkout@v2 14 | - name: Build the image 15 | run: cd ansible && docker build -t test:test . -------------------------------------------------------------------------------- /automated-tests/user-store/run.sh: -------------------------------------------------------------------------------- 1 | docker run -d --net none --name user-store-db mongo:3.1; 2 | docker run -it --rm --net container:user-store-db magnitus/automated-tests:4.1-node-user-store; 3 | docker run -it --rm --net container:user-store-db magnitus/automated-tests:0.10-node-user-store; 4 | docker stop user-store-db; 5 | docker rm user-store-db; 6 | 7 | 8 | -------------------------------------------------------------------------------- /electron-app/dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:latest 2 | RUN apt-get update -y && \ 3 | apt-get install -y libgtk2.0-0 && \ 4 | apt-get install -y libnotify-dev && \ 5 | apt-get install -y libgconf-2-4 && \ 6 | apt-get install -y libnss3 7 | COPY ["./entryScript.sh", "/opt/entryScript.sh"] 8 | RUN chmod +x /opt/entryScript.sh 9 | ENTRYPOINT ["/bin/bash", "/opt/entryScript.sh"] -------------------------------------------------------------------------------- /node-app/base-image/example3/dockerfile: -------------------------------------------------------------------------------- 1 | FROM magnitus/node-app:4 2 | 3 | ENV UID="1000" 4 | 5 | COPY "app/*" ${APP_DIR}/ 6 | COPY "shared/user-store" ${SHARED_DIR}/user-store 7 | COPY "shared/array/capitalize-array" ${SHARED_DIR}/array/capitalize-array 8 | COPY "shared/array/sort-array" ${SHARED_DIR}/array/sort-array 9 | 10 | RUN finalize.sh 11 | 12 | USER $UID 13 | -------------------------------------------------------------------------------- /node-app/base-image/example3/shared/array/sort-array/index.js: -------------------------------------------------------------------------------- 1 | function compare(a, b) 2 | { 3 | if(a.length < b.length) 4 | { 5 | return -1; 6 | } 7 | 8 | if(a.length > b.length) 9 | { 10 | return 1; 11 | } 12 | 13 | return 0; 14 | } 15 | 16 | module.exports = function(array) { 17 | return array.sort(compare); 18 | } 19 | 20 | -------------------------------------------------------------------------------- /react-build/example/docker-compose.yml: -------------------------------------------------------------------------------- 1 | app: 2 | container_name: react-compiler-example 3 | image: magnitus/react-compiler:latest-slim 4 | environment: 5 | - BUILD_FILE=/opt/build.json 6 | - OUTPUT_UID=1000 7 | volumes: 8 | - ./build.json:/opt/build.json 9 | - ./app/javascript:/opt/app/javascript 10 | - ./lib:/opt/lib 11 | - ./app/dist:/opt/dist 12 | -------------------------------------------------------------------------------- /sbt/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM openjdk:14-jdk-buster 2 | 3 | RUN apt-get update && apt-get install -y curl gnupg 4 | RUN echo "deb https://dl.bintray.com/sbt/debian/ /" > /etc/apt/sources.list.d/sbt.list 5 | RUN curl -sL "https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x2EE0EA64E40A89B84B2DF73499E82A75642AC823" | apt-key add 6 | RUN apt-get update && apt-get install -y sbt 7 | RUN sbt --version -------------------------------------------------------------------------------- /.github/workflows/build_ssh_encryption.yml: -------------------------------------------------------------------------------- 1 | name: Build Ssh Encryption Image 2 | 3 | on: 4 | push: 5 | paths: 6 | - 'ssh-encryption/**' 7 | 8 | jobs: 9 | publish: 10 | name: Build Image 11 | runs-on: ubuntu-18.04 12 | steps: 13 | - uses: actions/checkout@v2 14 | - name: Build the image 15 | run: cd ssh-encryption/image && docker build -t test:test . -------------------------------------------------------------------------------- /.github/workflows/build_remote_terraform.yml: -------------------------------------------------------------------------------- 1 | name: Build Remote Terraform Image 2 | 3 | on: 4 | push: 5 | paths: 6 | - 'remote-terraform/**' 7 | 8 | jobs: 9 | publish: 10 | name: Build Image 11 | runs-on: ubuntu-18.04 12 | steps: 13 | - uses: actions/checkout@v2 14 | - name: Build the image 15 | run: cd remote-terraform && docker build -t test:test . -------------------------------------------------------------------------------- /node-app/dockerfile-builder/code/dockerfile: -------------------------------------------------------------------------------- 1 | FROM docker:1.11 2 | 3 | ENV TEMPLATE_PATH /opt/build/template 4 | ENV APP_DIR /opt/app 5 | ENV SHARED_DIR /opt/shared 6 | ENV OUTPUT_DIR /opt/output 7 | 8 | RUN apk add --no-cache nodejs 9 | COPY ["app/", "/opt/build/"] 10 | RUN (cd /opt/build; npm install) 11 | 12 | WORKDIR /opt/build 13 | 14 | ENTRYPOINT ["/usr/bin/npm"] 15 | CMD ["start"] 16 | 17 | -------------------------------------------------------------------------------- /node-app/base-image/example5/shared/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "is-prime", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "licenses": [ 6 | { 7 | "type": "MIT License", 8 | "url": "http://mit-license.org/" 9 | } 10 | ], 11 | "dependencies": { 12 | }, 13 | "devDependencies": { 14 | }, 15 | "license": "MIT", 16 | "directories": { 17 | }, 18 | "scripts": { 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /node-app/base-image/example4/shared/module1/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "module1", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "licenses": [ 6 | { 7 | "type": "MIT License", 8 | "url": "http://mit-license.org/" 9 | } 10 | ], 11 | "dependencies": { 12 | }, 13 | "devDependencies": { 14 | }, 15 | "license": "MIT", 16 | "directories": { 17 | }, 18 | "scripts": { 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /node-app/image-builder/example2/shared/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "is-prime", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "licenses": [ 6 | { 7 | "type": "MIT License", 8 | "url": "http://mit-license.org/" 9 | } 10 | ], 11 | "dependencies": { 12 | }, 13 | "devDependencies": { 14 | }, 15 | "license": "MIT", 16 | "directories": { 17 | }, 18 | "scripts": { 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /certificate/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM debian:stretch 2 | 3 | ENV KEY_FILE domain.key 4 | ENV CSR_FILE domain.csr 5 | ENV CERTIFICATE_FILE domain.crt 6 | ENV OUTPUT_DIR /opt/output 7 | ENV KEY_BITS 2048 8 | ENV CERTIFICATE_DURATION 365 9 | 10 | RUN apt-get update && apt-get install -y openssl && apt-get install -y python 11 | 12 | COPY generateCertificate.py /opt/scripts/ 13 | 14 | CMD ["python", "/opt/scripts/generateCertificate.py"] 15 | -------------------------------------------------------------------------------- /node-app/base-dev-image/example/shared/module1/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "module1", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "licenses": [ 6 | { 7 | "type": "MIT License", 8 | "url": "http://mit-license.org/" 9 | } 10 | ], 11 | "dependencies": { 12 | }, 13 | "devDependencies": { 14 | }, 15 | "license": "MIT", 16 | "directories": { 17 | }, 18 | "scripts": { 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /node-app/base-image/example3/shared/array/sort-array/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sort-array", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "licenses": [ 6 | { 7 | "type": "MIT License", 8 | "url": "http://mit-license.org/" 9 | } 10 | ], 11 | "dependencies": { 12 | }, 13 | "devDependencies": { 14 | }, 15 | "license": "MIT", 16 | "directories": { 17 | }, 18 | "scripts": { 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /node-app/base-image/example/shared/capitalize-array/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "capitalize-array", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "licenses": [ 6 | { 7 | "type": "MIT License", 8 | "url": "http://mit-license.org/" 9 | } 10 | ], 11 | "dependencies": { 12 | }, 13 | "devDependencies": { 14 | }, 15 | "license": "MIT", 16 | "directories": { 17 | }, 18 | "scripts": { 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /node-app/image-builder/example/shared/capitalize-array/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "capitalize-array", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "licenses": [ 6 | { 7 | "type": "MIT License", 8 | "url": "http://mit-license.org/" 9 | } 10 | ], 11 | "dependencies": { 12 | }, 13 | "devDependencies": { 14 | }, 15 | "license": "MIT", 16 | "directories": { 17 | }, 18 | "scripts": { 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /network-setup/image/zonefile.j2: -------------------------------------------------------------------------------- 1 | $TTL {{ ttl.default }} 2 | $ORIGIN {{ domain }}. 3 | @ IN SOA nameserver.{{ domain }}. email.{{ domain }}. ( 4 | {{ timestamp }}; 5 | 7200; 6 | 3600; 7 | 1209600; 8 | 3600; 9 | 10 | ) 11 | IN NS nameserver.{{ domain }}. 12 | nameserver {{ ttl.default }} IN A {{ ip }} 13 | {% for static_host in network.static_hosts %} 14 | {{ static_host.name }} {{ ttl.short }} IN A {{ static_host.ip }} 15 | {% endfor %} -------------------------------------------------------------------------------- /node-app/base-image/example3/shared/array/capitalize-array/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "capitalize-array", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "licenses": [ 6 | { 7 | "type": "MIT License", 8 | "url": "http://mit-license.org/" 9 | } 10 | ], 11 | "dependencies": { 12 | }, 13 | "devDependencies": { 14 | }, 15 | "license": "MIT", 16 | "directories": { 17 | }, 18 | "scripts": { 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /node-app/dockerfile-builder/example/shared/capitalize-array/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "capitalize-array", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "licenses": [ 6 | { 7 | "type": "MIT License", 8 | "url": "http://mit-license.org/" 9 | } 10 | ], 11 | "dependencies": { 12 | }, 13 | "devDependencies": { 14 | }, 15 | "license": "MIT", 16 | "directories": { 17 | }, 18 | "scripts": { 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /node-app/base-image/example4/shared/module2/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "module2", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "licenses": [ 6 | { 7 | "type": "MIT License", 8 | "url": "http://mit-license.org/" 9 | } 10 | ], 11 | "dependencies": { 12 | "xregexp": "2.x" 13 | }, 14 | "devDependencies": { 15 | }, 16 | "license": "MIT", 17 | "directories": { 18 | }, 19 | "scripts": { 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /node-app/base-image/example5/shared/index.js: -------------------------------------------------------------------------------- 1 | module.exports = function(candidate) { 2 | var max = Math.floor(Math.sqrt(candidate)); 3 | var index = 3; 4 | if(candidate % 2 == 0 && candidate != 2) 5 | { 6 | return false; 7 | } 8 | while(index <= max) 9 | { 10 | if(candidate % index == 0) 11 | { 12 | return false; 13 | } 14 | index += 2; 15 | } 16 | return true; 17 | } 18 | -------------------------------------------------------------------------------- /node-app/dockerfile-builder/example/docker-compose.yml: -------------------------------------------------------------------------------- 1 | app: 2 | container_name: build-example 3 | image: magnitus/node-app:dockerfile-builder 4 | environment: 5 | - UID=1000 6 | - OUTPUT_UID=1000 7 | - OUTPUT_IMAGE=magnitus/node-app:dockerfile-builder-example 8 | - IGNORE=.+~$$ 9 | volumes: 10 | - ./app:/opt/app 11 | - ./shared:/opt/shared 12 | - ./output:/opt/output 13 | - /var/run/docker.sock:/var/run/docker.sock 14 | -------------------------------------------------------------------------------- /node-app/base-dev-image/example/shared/module2/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "module2", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "licenses": [ 6 | { 7 | "type": "MIT License", 8 | "url": "http://mit-license.org/" 9 | } 10 | ], 11 | "dependencies": { 12 | "xregexp": "2.x" 13 | }, 14 | "devDependencies": { 15 | }, 16 | "license": "MIT", 17 | "directories": { 18 | }, 19 | "scripts": { 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /node-app/image-builder/example2/shared/index.js: -------------------------------------------------------------------------------- 1 | module.exports = function(candidate) { 2 | var max = Math.floor(Math.sqrt(candidate)); 3 | var index = 3; 4 | if(candidate % 2 == 0 && candidate != 2) 5 | { 6 | return false; 7 | } 8 | while(index <= max) 9 | { 10 | if(candidate % index == 0) 11 | { 12 | return false; 13 | } 14 | index += 2; 15 | } 16 | return true; 17 | } 18 | -------------------------------------------------------------------------------- /pulsar-orchestration/README.md: -------------------------------------------------------------------------------- 1 | # About 2 | 3 | This is a "high availability" local orchestration for Apache Pulsar (yes, **high availability** and **local** are somewhat of an oxymoron, hence the quotes) 4 | 5 | This not meant to be used in production. There is an official Helm chart for that: http://pulsar.apache.org/docs/en/helm-install/ 6 | 7 | This is more of a personal exercise to get some hands on practice on how the different components of a Pulsar cluster fit together. -------------------------------------------------------------------------------- /react-build/example/app/javascript/header.jsx: -------------------------------------------------------------------------------- 1 | var React = require('react'); 2 | var ReactDOM = require('react-dom'); 3 | 4 | module.exports = React.createClass({ 5 | render: function() { 6 | return ( 7 |
8 |

Welcome to React Lotto!

9 |

The lotto where you dream less, but the mathematical expectation of your gains is much higher!

10 |
11 | ); 12 | } 13 | }); 14 | -------------------------------------------------------------------------------- /hapi-service/hello-world/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "geev-hello-word", 3 | "version": "0.1.0", 4 | "description": "Tractr private app.", 5 | "author": "Eric Vallee ", 6 | "main": "./index.js", 7 | "repository": { 8 | "type": "git", 9 | "url": "git@bitbucket.org:tractrs/geev-api.git" 10 | }, 11 | "dependencies": { 12 | "hapi": "13.x" 13 | }, 14 | "scripts": { 15 | "start": "node ./index.js" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /node-app/base-image/example/shared/user-store/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "user-store", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "licenses": [ 6 | { 7 | "type": "MIT License", 8 | "url": "http://mit-license.org/" 9 | } 10 | ], 11 | "dependencies": { 12 | }, 13 | "devDependencies": { 14 | }, 15 | "localDependencies": ["capitalize-array"], 16 | "license": "MIT", 17 | "directories": { 18 | }, 19 | "scripts": { 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /node-app/base-image/example2/app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sample-hapi-app", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "licenses": [ 6 | { 7 | "type": "MIT License", 8 | "url": "http://mit-license.org/" 9 | } 10 | ], 11 | "dependencies": { 12 | "hapi": "13.x" 13 | }, 14 | "devDependencies": { 15 | }, 16 | "license": "MIT", 17 | "directories": { 18 | }, 19 | "scripts": { 20 | "start": "node index.js" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /node-app/dockerfile-builder/templates/docker-compose.yml: -------------------------------------------------------------------------------- 1 | app: 2 | container_name: <> 3 | image: magnitus/node-app:dockerfile-builder 4 | environment: 5 | - UID=<<1000>> 6 | - OUTPUT_UID=<<1000>> 7 | - OUTPUT_IMAGE=<> 8 | - IGNORE=.+~$$ 9 | volumes: 10 | - <<./app>>:/opt/app 11 | - <<./shared>>:/opt/shared 12 | - <<./output>>:/opt/output 13 | - /var/run/docker.sock:/var/run/docker.sock 14 | -------------------------------------------------------------------------------- /node-app/image-builder/example/shared/user-store/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "user-store", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "licenses": [ 6 | { 7 | "type": "MIT License", 8 | "url": "http://mit-license.org/" 9 | } 10 | ], 11 | "dependencies": { 12 | }, 13 | "devDependencies": { 14 | }, 15 | "localDependencies": ["capitalize-array"], 16 | "license": "MIT", 17 | "directories": { 18 | }, 19 | "scripts": { 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /react-build/example-onbuild/app/javascript/header.jsx: -------------------------------------------------------------------------------- 1 | var React = require('react'); 2 | var ReactDOM = require('react-dom'); 3 | 4 | module.exports = React.createClass({ 5 | render: function() { 6 | return ( 7 |
8 |

Welcome to React Lotto!

9 |

The lotto where you dream less, but the mathematical expectation of your gains is much higher!

10 |
11 | ); 12 | } 13 | }); 14 | -------------------------------------------------------------------------------- /node-app/dockerfile-builder/example/shared/user-store/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "user-store", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "licenses": [ 6 | { 7 | "type": "MIT License", 8 | "url": "http://mit-license.org/" 9 | } 10 | ], 11 | "dependencies": { 12 | }, 13 | "devDependencies": { 14 | }, 15 | "localDependencies": ["capitalize-array"], 16 | "license": "MIT", 17 | "directories": { 18 | }, 19 | "scripts": { 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /node-app/image-builder/code/app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "builder-app", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "licenses": [ 6 | { 7 | "type": "MIT License", 8 | "url": "http://mit-license.org/" 9 | } 10 | ], 11 | "dependencies": { 12 | "act-on-modules": "0.1.0" 13 | }, 14 | "devDependencies": { 15 | }, 16 | "license": "MIT", 17 | "directories": { 18 | }, 19 | "scripts": { 20 | "start": "node index.js" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /node-app/base-image/example3/shared/user-store/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "user-store", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "licenses": [ 6 | { 7 | "type": "MIT License", 8 | "url": "http://mit-license.org/" 9 | } 10 | ], 11 | "dependencies": { 12 | }, 13 | "devDependencies": { 14 | }, 15 | "localDependencies": ["capitalize-array", "sort-array"], 16 | "license": "MIT", 17 | "directories": { 18 | }, 19 | "scripts": { 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /pulsar-orchestration/zookeeper-conf/zoo.cfg: -------------------------------------------------------------------------------- 1 | #Taken from recommended zookeeper configuration file with minimal adjustments 2 | tickTime=2000 3 | initLimit=10 4 | syncLimit=5 5 | dataDir=/data 6 | dataLogDir=/datalog 7 | clientPort=2181 8 | admin.enableServer=true 9 | admin.serverPort=9990 10 | autopurge.snapRetainCount=3 11 | autopurge.purgeInterval=1 12 | forceSync=yes 13 | server.1=zookeeper-one:2888:3888;2181 14 | server.2=zookeeper-two:2888:3888;2181 15 | server.3=zookeeper-three:2888:3888;2181 -------------------------------------------------------------------------------- /electron-app/app/main.js: -------------------------------------------------------------------------------- 1 | const electron = require('electron'); 2 | 3 | electron.crashReporter.start(); 4 | 5 | var mainWindow = null; 6 | 7 | electron.app.on('window-all-closed', function() { 8 | electron.app.quit(); 9 | }); 10 | 11 | electron.app.on('ready', function() { 12 | mainWindow = new electron.BrowserWindow(); 13 | mainWindow.loadURL('file://' + __dirname + '/index.html'); 14 | mainWindow.on('closed', function() { 15 | mainWindow = null; 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /network-setup/image/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3-stretch 2 | 3 | ENV CONFIG_DIRECTORY /etc/network-setup 4 | ENV TEMPLATE_DIRECTORY /opt/templates 5 | ENV SCRIPT_DIRECTORY /opt/scripts 6 | 7 | RUN pip install Jinja2 pyyaml docker && mkdir -p $SCRIPT_DIRECTORY && mkdir -p $TEMPLATE_DIRECTORY 8 | 9 | ENV DNS_IMAGE=coredns/coredns:latest 10 | ENV DHCP_IMAGE=magnitus/isc-dhcp-server:latest 11 | 12 | COPY setup.py $SCRIPT_DIRECTORY/ 13 | COPY *.j2 $TEMPLATE_DIRECTORY/ 14 | 15 | CMD ["/opt/scripts/setup.py"] -------------------------------------------------------------------------------- /node-app/base-image/example/app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sample-app", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "licenses": [ 6 | { 7 | "type": "MIT License", 8 | "url": "http://mit-license.org/" 9 | } 10 | ], 11 | "dependencies": { 12 | }, 13 | "devDependencies": { 14 | }, 15 | "localDependencies": ["user-store"], 16 | "license": "MIT", 17 | "directories": { 18 | }, 19 | "scripts": { 20 | "start": "node index.js" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /node-app/base-image/example3/app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sample-app", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "licenses": [ 6 | { 7 | "type": "MIT License", 8 | "url": "http://mit-license.org/" 9 | } 10 | ], 11 | "dependencies": { 12 | }, 13 | "devDependencies": { 14 | }, 15 | "localDependencies": ["user-store"], 16 | "license": "MIT", 17 | "directories": { 18 | }, 19 | "scripts": { 20 | "start": "node index.js" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /node-app/image-builder/example/app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sample-app", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "licenses": [ 6 | { 7 | "type": "MIT License", 8 | "url": "http://mit-license.org/" 9 | } 10 | ], 11 | "dependencies": { 12 | }, 13 | "devDependencies": { 14 | }, 15 | "localDependencies": ["user-store"], 16 | "license": "MIT", 17 | "directories": { 18 | }, 19 | "scripts": { 20 | "start": "node index.js" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /node-app/base-image/example4/app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sample-app", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "licenses": [ 6 | { 7 | "type": "MIT License", 8 | "url": "http://mit-license.org/" 9 | } 10 | ], 11 | "dependencies": { 12 | }, 13 | "devDependencies": { 14 | }, 15 | "localDependencies": ["module1","module2"], 16 | "license": "MIT", 17 | "directories": { 18 | }, 19 | "scripts": { 20 | "start": "node index.js" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /node-app/dockerfile-builder/example/app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sample-app", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "licenses": [ 6 | { 7 | "type": "MIT License", 8 | "url": "http://mit-license.org/" 9 | } 10 | ], 11 | "dependencies": { 12 | }, 13 | "devDependencies": { 14 | }, 15 | "localDependencies": ["user-store"], 16 | "license": "MIT", 17 | "directories": { 18 | }, 19 | "scripts": { 20 | "start": "node index.js" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /node-app/base-dev-image/example/app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sample-app", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "licenses": [ 6 | { 7 | "type": "MIT License", 8 | "url": "http://mit-license.org/" 9 | } 10 | ], 11 | "dependencies": { 12 | }, 13 | "devDependencies": { 14 | }, 15 | "localDependencies": ["module1","module2"], 16 | "license": "MIT", 17 | "directories": { 18 | }, 19 | "scripts": { 20 | "start": "node index.js" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /node-app/dockerfile-builder/code/app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "builder-app", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "licenses": [ 6 | { 7 | "type": "MIT License", 8 | "url": "http://mit-license.org/" 9 | } 10 | ], 11 | "dependencies": { 12 | "chownr": "1.x", 13 | "cpr": "1.x" 14 | }, 15 | "devDependencies": { 16 | }, 17 | "license": "MIT", 18 | "directories": { 19 | }, 20 | "scripts": { 21 | "start": "node index.js" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /react-build/example/app/javascript/index.jsx: -------------------------------------------------------------------------------- 1 | var React = require('react'); 2 | var ReactDOM = require('react-dom'); 3 | var App = require('app'); 4 | 5 | var reactElement = React.createElement(App, {'balls': 50, 6 | 'draws': 3, 7 | 'initPot': 200, 8 | 'winRatios': [0.375, 0.075, 0.05]}); 9 | ReactDOM.render(reactElement, document.getElementById('app')); 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.github/workflows/publish_ansible.yml: -------------------------------------------------------------------------------- 1 | name: Publish Ansible Image 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | paths: 8 | - 'ansible/**' 9 | 10 | jobs: 11 | publish: 12 | name: Publish Image 13 | runs-on: ubuntu-18.04 14 | steps: 15 | - uses: actions/checkout@v2 16 | - name: Log into registry 17 | run: echo "${{ secrets.DOCKER_HUB_TOKEN }}" | docker login -u magnitus --password-stdin 18 | - name: Publish the image 19 | run: cd ansible && ./push_image.sh -------------------------------------------------------------------------------- /node-app/image-builder/code/server/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "builder-app-server", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "licenses": [ 6 | { 7 | "type": "MIT License", 8 | "url": "http://mit-license.org/" 9 | } 10 | ], 11 | "dependencies": { 12 | "hapi": "13.x", 13 | "inert": "" 14 | }, 15 | "devDependencies": { 16 | }, 17 | "license": "MIT", 18 | "directories": { 19 | }, 20 | "scripts": { 21 | "start": "node index.js" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /node-app/image-builder/example/docker-compose.yml: -------------------------------------------------------------------------------- 1 | app: 2 | container_name: build-image-example 3 | image: magnitus/node-app:image-builder 4 | environment: 5 | - UID=1000 6 | - OUTPUT_IMAGE=magnitus/node-app:image-builder-example 7 | - IGNORE=.+~$$ 8 | - EXTERNAL_PORT=8080 9 | - DOCKER_LOCALHOST=172.17.0.1 10 | - CACHE=no 11 | volumes: 12 | - ./app:/opt/app 13 | - ./shared:/opt/shared 14 | - /var/run/docker.sock:/var/run/docker.sock 15 | ports: 16 | - "8080:8080" 17 | -------------------------------------------------------------------------------- /react-build/example-onbuild/app/javascript/index.jsx: -------------------------------------------------------------------------------- 1 | var React = require('react'); 2 | var ReactDOM = require('react-dom'); 3 | var App = require('app'); 4 | 5 | var reactElement = React.createElement(App, {'balls': 50, 6 | 'draws': 3, 7 | 'initPot': 200, 8 | 'winRatios': [0.375, 0.075, 0.05]}); 9 | ReactDOM.render(reactElement, document.getElementById('app')); 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /node-app/base-image/example5/app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sample-test", 3 | "version": "1.0.0", 4 | "licenses": [ 5 | { 6 | "type": "MIT License", 7 | "url": "http://mit-license.org/" 8 | } 9 | ], 10 | "dependencies": { 11 | "nodeunit": "^0.9.1" 12 | }, 13 | "devDependencies": { 14 | }, 15 | "localDependencies": ["is-prime"], 16 | "license": "MIT", 17 | "directories": { 18 | }, 19 | "scripts": { 20 | "test": "./node_modules/nodeunit/bin/nodeunit test" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /node-app/image-builder/example2/app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sample-test", 3 | "version": "1.0.0", 4 | "licenses": [ 5 | { 6 | "type": "MIT License", 7 | "url": "http://mit-license.org/" 8 | } 9 | ], 10 | "dependencies": { 11 | "nodeunit": "^0.9.1" 12 | }, 13 | "devDependencies": { 14 | }, 15 | "localDependencies": ["is-prime"], 16 | "license": "MIT", 17 | "directories": { 18 | }, 19 | "scripts": { 20 | "test": "./node_modules/nodeunit/bin/nodeunit test" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /isc-dhcp-server/Dockerfile-amd64: -------------------------------------------------------------------------------- 1 | FROM debian:stretch-slim 2 | 3 | RUN apt-get update -y && \ 4 | apt-get install -y isc-dhcp-server && \ 5 | apt-get autoremove -y && \ 6 | apt-get clean -y 7 | 8 | ENV RUNTIME_USER=www-data 9 | ENV SOURCE_CONF_PATH=/opt/dhcp/dhcpd.conf 10 | ENV IP_VERSION=4 11 | ENV INTERFACE=eth0 12 | 13 | ENV CONF_PATH=/etc/dhcp/dhcp.conf 14 | ENV LEASE_PATH=/var/lib/dhcp/dhcp.lease 15 | 16 | COPY entrypoint.sh /opt/entrypoint.sh 17 | RUN chmod +x /opt/entrypoint.sh 18 | 19 | CMD ["/opt/entrypoint.sh"] -------------------------------------------------------------------------------- /electron-app/entryScript.sh: -------------------------------------------------------------------------------- 1 | echo "${_USER}:x:${_UID}:${_UID}:${_USER},,,:/home/${_USER}:/bin/bash" >> /etc/passwd && \ 2 | echo "${_USER}:x:${_UID}:" >> /etc/group && \ 3 | chown $_UID:$_UID -R /home/$_USER 4 | su $_USER <<'EOF' 5 | if [ ! -d "/home/${_USER}/app/node_modules" ]; then 6 | (cd /home/$_USER/app; npm install; npm install electron-rebuild; /home/$_USER/app/node_modules/.bin/electron-rebuild; npm install electron-prebuilt) 7 | fi 8 | /home/$_USER/app/node_modules/electron-prebuilt/dist/electron /home/$_USER/app; 9 | EOF 10 | -------------------------------------------------------------------------------- /isc-dhcp-server/Dockerfile-arm64: -------------------------------------------------------------------------------- 1 | FROM arm64v8/debian:stretch-slim 2 | 3 | RUN apt-get update -y && \ 4 | apt-get install -y isc-dhcp-server && \ 5 | apt-get autoremove -y && \ 6 | apt-get clean -y 7 | 8 | ENV RUNTIME_USER=www-data 9 | ENV SOURCE_CONF_PATH=/opt/dhcp/dhcpd.conf 10 | ENV IP_VERSION=4 11 | ENV INTERFACE=eth0 12 | 13 | ENV CONF_PATH=/etc/dhcp/dhcp.conf 14 | ENV LEASE_PATH=/var/lib/dhcp/dhcp.lease 15 | 16 | COPY entrypoint.sh /opt/entrypoint.sh 17 | RUN chmod +x /opt/entrypoint.sh 18 | 19 | CMD ["/opt/entrypoint.sh"] -------------------------------------------------------------------------------- /.github/workflows/publish_ssh_encryption.yml: -------------------------------------------------------------------------------- 1 | name: Publish Ssh Encryption Image 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | paths: 8 | - 'ssh-encryption/**' 9 | 10 | jobs: 11 | publish: 12 | name: Publish Image 13 | runs-on: ubuntu-18.04 14 | steps: 15 | - uses: actions/checkout@v2 16 | - name: Log into registry 17 | run: echo "${{ secrets.DOCKER_HUB_TOKEN }}" | docker login -u magnitus --password-stdin 18 | - name: Publish the image 19 | run: cd ssh-encryption && ./push_image.sh -------------------------------------------------------------------------------- /node-app/image-builder/example2/docker-compose.yml: -------------------------------------------------------------------------------- 1 | app: 2 | container_name: build-image-example2 3 | image: magnitus/node-app:image-builder 4 | environment: 5 | - UID=1000 6 | - OUTPUT_IMAGE=magnitus/node-app:image-builder-example2 7 | - IGNORE=.+~$$ 8 | - EXTERNAL_PORT=8080 9 | - DOCKER_LOCALHOST=172.17.0.1 10 | - CACHE=no 11 | - NPM_COMMAND=test 12 | volumes: 13 | - ./app:/opt/app 14 | - ./shared:/opt/shared 15 | - /var/run/docker.sock:/var/run/docker.sock 16 | ports: 17 | - "8080:8080" 18 | -------------------------------------------------------------------------------- /.github/workflows/publish_remote_terraform.yml: -------------------------------------------------------------------------------- 1 | name: Publish Remote Terraform Image 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | paths: 8 | - 'remote-terraform/**' 9 | 10 | jobs: 11 | publish: 12 | name: Publish Image 13 | runs-on: ubuntu-18.04 14 | steps: 15 | - uses: actions/checkout@v2 16 | - name: Log into registry 17 | run: echo "${{ secrets.DOCKER_HUB_TOKEN }}" | docker login -u magnitus --password-stdin 18 | - name: Publish the image 19 | run: cd remote-terraform && ./push_image.sh -------------------------------------------------------------------------------- /node-app/image-builder/templates/docker-compose.yml: -------------------------------------------------------------------------------- 1 | app: 2 | container_name: <> 3 | image: magnitus/node-app:image-builder 4 | environment: 5 | - UID=<<1000>> 6 | - OUTPUT_IMAGE=<> 7 | - IGNORE=<<.+~$$>> 8 | - EXTERNAL_PORT=<<8080>> 9 | - DOCKER_LOCALHOST=<<172.17.0.1>> 10 | - CACHE=<> 11 | volumes: 12 | - <<./app>>:/opt/app 13 | - <<./shared>>:/opt/shared 14 | - /var/run/docker.sock:/var/run/docker.sock 15 | ports: 16 | - "<<8080>>:8080" 17 | -------------------------------------------------------------------------------- /ssh-encryption/example/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.7' 2 | services: 3 | encrypt: 4 | build: ../image 5 | command: ssh-encrypt 6 | environment: 7 | FILE: /opt/target/test.txt 8 | PUBLIC_KEY: /opt/.ssh/id_rsa.pub 9 | volumes: 10 | - ./:/opt/target 11 | - ~/.ssh:/opt/.ssh 12 | decrypt: 13 | build: ../image 14 | command: ssh-decrypt 15 | environment: 16 | FILE: /opt/target/test.txt 17 | PRIVATE_KEY: /opt/.ssh/id_rsa 18 | volumes: 19 | - ./:/opt/target 20 | - ~/.ssh:/opt/.ssh -------------------------------------------------------------------------------- /chrome/docker-compose.yml: -------------------------------------------------------------------------------- 1 | chrome: 2 | image: magnitus/chrome:stable 3 | net: host 4 | cpuset: 0,1 5 | mem_limit: 1G 6 | devices: 7 | - /dev/snd:/dev/snd 8 | volumes: 9 | - /tmp/.X11-unix:/tmp/.X11-unix 10 | - /dev/shm:/dev/shm 11 | - /run/dbus:/run/dbus 12 | - /var/run/dbus/system_bus_socket:/var/run/dbus/system_bus_socket 13 | - $HOME/Downloads:/home/chrome/Downloads 14 | - $HOME/.config/google-chrome:/data 15 | environment: 16 | - DISPLAY=$DISPLAY 17 | - _UID=1000 18 | -------------------------------------------------------------------------------- /node-app/image-builder/code/dockerfile: -------------------------------------------------------------------------------- 1 | FROM docker:1.11 2 | 3 | ENV TEMPLATE_PATH /opt/build/template 4 | ENV APP_DIR /opt/app 5 | ENV SHARED_DIR /opt/shared 6 | 7 | ENV SERVER_DIR /opt/server 8 | 9 | ENV DEFAULT_SOURCE_IMAGE magnitus/node-app:4 10 | 11 | RUN apk add --no-cache nodejs && apk add --no-cache wget 12 | 13 | COPY ["app/", "/opt/build/"] 14 | RUN (cd /opt/build; npm install) 15 | 16 | COPY ["server/", "${SERVER_DIR}"] 17 | RUN (cd ${SERVER_DIR}; npm install) 18 | 19 | WORKDIR /opt/build 20 | 21 | ENTRYPOINT ["/usr/bin/npm"] 22 | CMD ["start"] 23 | 24 | -------------------------------------------------------------------------------- /node-app/image-builder/example/docker-compose-slim.yml: -------------------------------------------------------------------------------- 1 | app: 2 | container_name: build-image-example-slim 3 | image: magnitus/node-app:image-builder 4 | environment: 5 | - SOURCE_IMAGE=magnitus/node-app:4-slim 6 | - UID=1000 7 | - OUTPUT_IMAGE=magnitus/node-app:image-builder-example-slim 8 | - IGNORE=.+~$$ 9 | - EXTERNAL_PORT=8080 10 | - DOCKER_LOCALHOST=172.17.0.1 11 | - CACHE=no 12 | volumes: 13 | - ./app:/opt/app 14 | - ./shared:/opt/shared 15 | - /var/run/docker.sock:/var/run/docker.sock 16 | ports: 17 | - "8080:8080" 18 | -------------------------------------------------------------------------------- /pyspark/README.md: -------------------------------------------------------------------------------- 1 | # About 2 | 3 | Just a dockerfile I wrote to try out the code of a pyspark course locally. 4 | 5 | I followed the installation instructions from the course (tailored for an ubuntu vm) and made a few adjustments where needed. 6 | 7 | I will make adjustments to this image as needed to follow the course. 8 | 9 | # Usage 10 | 11 | Launch the container by running: 12 | 13 | ``` 14 | ./run.sh 15 | ``` 16 | 17 | Find out the connection string by typing: 18 | 19 | ``` 20 | docker logs pyspark-jupyter-notebook 21 | ``` 22 | 23 | Plug the connection string in your browser. -------------------------------------------------------------------------------- /jedit/dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:14.04 2 | RUN apt-get update && \ 3 | apt-get install -y openjdk-7-jdk && \ 4 | apt-get install -y wget && \ 5 | wget 'http://sourceforge.net/projects/jedit/files/jedit-devel/5.2pre1/jedit_5.2pre1_all.deb/download' --output-document=/opt/jedit_5.2pre1_all.deb && \ 6 | dpkg -i /opt/jedit_5.2pre1_all.deb && \ 7 | apt-get purge -y wget && \ 8 | apt-get clean && \ 9 | rm /opt/jedit_5.2pre1_all.deb 10 | COPY ["./entryScript.sh", "/opt/entryScript.sh"] 11 | RUN chmod +x /opt/entryScript.sh 12 | ENTRYPOINT ["/bin/bash", "/opt/entryScript.sh"] 13 | -------------------------------------------------------------------------------- /headless-factorio-server/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.4' 2 | services: 3 | factorio-headless-server: 4 | image: magnitus/factorio-headless-server:0.17.79 5 | build: . 6 | network_mode: "host" 7 | environment: 8 | GAME_NAME: "Friendly Game" 9 | GAME_DESCRIPTION: "Friendly Game" 10 | GAME_PASSWORD: "MyPasswordIsMighty" 11 | ADMIN_PLAYERS: "me,you" 12 | WHITELISTED_PLAYERS: "me,you" 13 | BIND_PORT: 8080 14 | BIND_IP: "0.0.0.0" 15 | volumes: 16 | - "factorio-data:/opt/data" 17 | restart: always 18 | 19 | volumes: 20 | factorio-data: {} -------------------------------------------------------------------------------- /node-app/image-builder/example2/docker-compose-slim.yml: -------------------------------------------------------------------------------- 1 | app: 2 | container_name: build-image-example2-slim 3 | image: magnitus/node-app:image-builder 4 | environment: 5 | - SOURCE_IMAGE=magnitus/node-app:4-slim 6 | - UID=1000 7 | - OUTPUT_IMAGE=magnitus/node-app:image-builder-example2-slim 8 | - IGNORE=.+~$$ 9 | - EXTERNAL_PORT=8080 10 | - DOCKER_LOCALHOST=172.17.0.1 11 | - CACHE=no 12 | - NPM_COMMAND=test 13 | volumes: 14 | - ./app:/opt/app 15 | - ./shared:/opt/shared 16 | - /var/run/docker.sock:/var/run/docker.sock 17 | ports: 18 | - "8080:8080" 19 | -------------------------------------------------------------------------------- /node-app/base-image/example5/app/test/index.js: -------------------------------------------------------------------------------- 1 | const isPrime = require('is-prime'); 2 | 3 | exports.main = { 4 | main: function(test) { 5 | test.expect(2); 6 | test.ok(isPrime(1) && isPrime(2) && isPrime(3) && isPrime(5) && isPrime(7) && isPrime(11) && isPrime(13) && isPrime(17) && isPrime(19) && isPrime(23), "Assert that library can detect primes."); 7 | test.ok((!isPrime(4)) && (!isPrime(6)) && (!isPrime(8)) && (!isPrime(9)) && (!isPrime(10)) && (!isPrime(12)) && (!isPrime(14)) && (!isPrime(15)), "Assert that library can identify non-primes."); 8 | test.done(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /node-app/image-builder/example2/app/test/index.js: -------------------------------------------------------------------------------- 1 | const isPrime = require('is-prime'); 2 | 3 | exports.main = { 4 | main: function(test) { 5 | test.expect(2); 6 | test.ok(isPrime(1) && isPrime(2) && isPrime(3) && isPrime(5) && isPrime(7) && isPrime(11) && isPrime(13) && isPrime(17) && isPrime(19) && isPrime(23), "Assert that library can detect primes."); 7 | test.ok((!isPrime(4)) && (!isPrime(6)) && (!isPrime(8)) && (!isPrime(9)) && (!isPrime(10)) && (!isPrime(12)) && (!isPrime(14)) && (!isPrime(15)), "Assert that library can identify non-primes."); 8 | test.done(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /pulsar-orchestration/configure_zookeeper.sh: -------------------------------------------------------------------------------- 1 | docker run --rm \ 2 | --network pulsar-internal \ 3 | --entrypoint="" \ 4 | apachepulsar/pulsar:2.5.1 bin/pulsar initialize-cluster-metadata \ 5 | --cluster pulsar-cluster-1 \ 6 | --zookeeper zookeeper-one:2181 \ 7 | --configuration-store zookeeper-one:2181 \ 8 | --web-service-url http://pulsar-broker:8080 \ 9 | --web-service-url-tls https://pulsar-broker:8443 \ 10 | --broker-service-url pulsar://pulsar-broker:6650 \ 11 | --broker-service-url-tls pulsar+ssl://pulsar-broker:6651 -------------------------------------------------------------------------------- /certificate/example/self-signed/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | services: 3 | self-signed-certificate-generator: 4 | image: magnitus/certificate-generator:latest 5 | environment: 6 | COUNTRY: CA 7 | STATE: Quebec 8 | CITY: Montreal 9 | ORGANIZATION: Any 10 | DEPARTMENT: IT 11 | EMAIL: email@mydomain.com 12 | DOMAINS: dev.mydomain.com;test.mydomain.com 13 | CERTIFICATE_DURATION: 1095 14 | KEY_FILE: "" 15 | CSR_FILE: "" 16 | CERTIFICATE_FILE: "" 17 | OUTPUT_CERTIFICATE_INFO: "true" 18 | volumes: 19 | - .:/opt/output 20 | -------------------------------------------------------------------------------- /node-app/dockerfile-builder/code/app/getCopyCmd.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | 4 | var ignoreRegex = process.env.IGNORE ? new RegExp(process.env.IGNORE) : null; 5 | 6 | module.exports = function (rootPath, destination) 7 | { 8 | //Plug app copy in template 9 | var copyAppCmd = "COPY ["; 10 | 11 | fs.readdirSync(rootPath).forEach((filename) => { 12 | if(filename != "node_modules" && (ignoreRegex && (!ignoreRegex.test(filename)))) 13 | { 14 | copyAppCmd += ("\""+path.join(rootPath, filename).replace('/opt', '.')+"\", "); 15 | } 16 | }); 17 | 18 | copyAppCmd += ("\""+destination+"/\"]"); 19 | return copyAppCmd; 20 | } 21 | -------------------------------------------------------------------------------- /react-build/code/app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-build", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "author": "Eric Vallee ", 6 | "licenses": [ 7 | { 8 | "type": "MIT License", 9 | "url": "http://mit-license.org/" 10 | } 11 | ], 12 | "dependencies": { 13 | "browserify": "13.x", 14 | "watchify": "3.x", 15 | "babelify": "7.x", 16 | "babel-preset-es2015": "6.x", 17 | "babel-preset-react": "6.x", 18 | "uglifyify": "3.x", 19 | "react": "15.x", 20 | "react-dom": "15.x", 21 | "redux": "3.x" 22 | }, 23 | "license": "MIT", 24 | "scripts": { 25 | "start": "node index.js" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /hapi-service/hello-world/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const Hapi = require('hapi'); 4 | 5 | const server = new Hapi.Server(); 6 | server.connection({ port: 8080 }); 7 | 8 | server.route([ 9 | { 10 | method: 'GET', 11 | path: '/hello_world', 12 | handler: function (request, reply) { 13 | reply('Hello World'); 14 | } 15 | } 16 | ]); 17 | 18 | server.start((err) => { 19 | if (err) { 20 | throw err; 21 | } 22 | console.log('Server running at:', server.info.uri); 23 | }); 24 | 25 | process.on('SIGTERM', () => { 26 | console.log('Sigterm received. Terminating hello world module...'); 27 | server.stop((err) => { 28 | process.exit(0); 29 | }); 30 | }); 31 | -------------------------------------------------------------------------------- /node-app/base-image/example2/app/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const Hapi = require('hapi'); 4 | 5 | const server = new Hapi.Server(); 6 | server.connection({ port: 8080 }); 7 | 8 | server.route([ 9 | { 10 | method: 'GET', 11 | path: '/hello_world', 12 | handler: function (request, reply) { 13 | reply('Hello, world!'); 14 | } 15 | } 16 | ]); 17 | 18 | server.start((err) => { 19 | if (err) { 20 | throw err; 21 | } 22 | console.log('Server running at:', server.info.uri); 23 | }); 24 | 25 | process.on('SIGTERM', () => { 26 | console.log('Sigterm received. Terminating process...'); 27 | server.stop((err) => { 28 | process.exit(0); 29 | }); 30 | }); 31 | -------------------------------------------------------------------------------- /network-setup/image/dhcp.conf.j2: -------------------------------------------------------------------------------- 1 | default-lease-time {{ lease_time.default }}; 2 | max-lease-time {{ lease_time.max }}; 3 | 4 | subnet {{ network.subnet }} netmask {{ network.mask }} { 5 | {% if network.router %} 6 | option routers {{ network.router }}; 7 | {% endif %} 8 | option broadcast-address {{ network.broadcast }}; 9 | option subnet-mask {{ network.mask }}; 10 | option domain-name-servers {{ ip }}; 11 | range {{ network.range }}; 12 | } 13 | 14 | {% for static_host in network.static_hosts %} 15 | host {{ static_host.name }} { 16 | option host-name "{{ static_host.name }}"; 17 | hardware ethernet {{ static_host.mac }}; 18 | fixed-address {{ static_host.ip }}; 19 | } 20 | {% endfor %} -------------------------------------------------------------------------------- /react-build/example/build.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "modules": { 4 | "*": ["/opt/lib"], 5 | "app": "/opt/app/javascript/app.jsx", 6 | "header": "/opt/app/javascript/header.jsx", 7 | "register-section": "/opt//app/javascript/register-section.jsx", 8 | "draw-section": "/opt/app/javascript/draw-section.jsx", 9 | "registration-feedback": "/opt/app/javascript/registration-feedback.jsx", 10 | "draw-feedback": "/opt/app/javascript/draw-feedback.jsx" 11 | }, 12 | "entrypoints": ["/opt/app/javascript/index.jsx"], 13 | "extensions": ["js", "jsx"], 14 | "watch": true, 15 | "minify": true, 16 | "dependencies": ["react", "react-dom"], 17 | "destination": "/opt/dist/bundle.js" 18 | } -------------------------------------------------------------------------------- /node-app/base-image/templates/dockerfile-template: -------------------------------------------------------------------------------- 1 | FROM magnitus/node-app:4 2 | 3 | #TODO: Set UID to whichever values makes sense 4 | ENV UID="1000" 5 | 6 | #TODO: your app content in /home/node-app/app 7 | COPY "app/*" ${APP_DIR}/ 8 | 9 | #TODO: Copy shared modules in shared modules directory 10 | # You can also simply omit the statement if you do not use shared modules 11 | COPY ["shared_modules/users", ${SHARED_DIR}/users] 12 | 13 | #TODO: Copy list of semi-colon separated npm module names that should be availabe by default everywhere in your project 14 | # You can also simply omit the declaration of this environment variable if you don't want to use any 15 | ENV NPM_MODULES="bluebird@3;xregexp@3" 16 | 17 | RUN finalize.sh 18 | 19 | USER $UID 20 | -------------------------------------------------------------------------------- /remote-terraform/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.8-slim-buster 2 | 3 | RUN apt-get update && apt-get install -y openssh-client sshpass 4 | RUN pip install ansible==2.9.6 5 | 6 | ENV ANSIBLE_STDOUT_CALLBACK=debug 7 | 8 | ENV ANSIBLE_USER=admin 9 | ENV PRIVATE_SSH_KEY=/opt/keys/id_rsa 10 | ENV INVENTORY=/opt/inventory 11 | ENV TERRAFORM_DIR=/opt/terraform 12 | 13 | ENV REMOTE_TERRAFORM_CONFIG_DIR=/opt/terraform_config 14 | ENV REMOTE_TERRAFORM_STATE_DIR=/opt/terraform_state 15 | ENV REMOTE_TERRAFORM_IMAGE=hashicorp/terraform:latest 16 | ENV REMOTE_CONTAINER_NAME=terraform 17 | 18 | WORKDIR /opt 19 | 20 | COPY ansible_scripts /opt/bastion_terraform 21 | COPY binaries/apply /bin/terraform_apply 22 | COPY binaries/plan /bin/terraform_plan 23 | 24 | CMD ["terraform_plan"] -------------------------------------------------------------------------------- /jedit/README.md: -------------------------------------------------------------------------------- 1 | # jEdit 2 | 3 | **NOTICE:** This image is not longer maintained as I no longer use jEdit as my primary editor. 4 | 5 | This is a dockerfile for the jEdit text editor. 6 | 7 | # Usage 8 | 9 | 1) Edit the docker-compose.yml file to convey your particular settings: 10 | 11 | - Change the _USER and _UID environment variables to reflect your particular executiong context 12 | - Change the /home/eric directory in the volumes to reflect your user 13 | - Change the /home/eric/Projects directory in the volumes to reflext the directory containing the files you want to edit with jEdit 14 | 15 | 2) Run docker-compose up 16 | 3) By differienciating the configuration and placement of the docker-compose.yml file, you can seperate your file editing environments. 17 | -------------------------------------------------------------------------------- /node-app/base-dev-image/code/finalize.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | if ! id "node-app" >/dev/null 2>&1; then 3 | echo "node-app:x:${UID}:${UID}:node-app,,,:/home/node-app:/bin/bash" >> /etc/passwd; 4 | echo "node-app:x:${UID}:" >> /etc/group; 5 | pwconv; 6 | grpconv; 7 | fi 8 | 9 | if [ ! -z "$ALWAYS_INSTALL" ] || [ ! -f "${HOME_DIR}/installation_done" ] ; then 10 | /opt/app-setup/resolve_dependencies.js; 11 | if [ -z "$ALWAYS_INSTALL" ] ; then 12 | touch ${HOME_DIR}/installation_done; 13 | fi 14 | fi 15 | 16 | chown -R ${UID}:${UID} /home/node-app; 17 | chown -R ${UID}:${UID} ${SHARED_DIR}; 18 | 19 | if [ -z "$NPM_COMMAND" ]; then 20 | NPM_COMMAND="start"; 21 | fi 22 | 23 | (cd ${APP_DIR}; su -c "${TOOL} run ${NPM_COMMAND}" node-app); 24 | -------------------------------------------------------------------------------- /react-build/example-onbuild/build.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "modules": { 4 | "*": ["/opt/lib"], 5 | "app": "/opt/app/javascript/app.jsx", 6 | "header": "/opt/app/javascript/header.jsx", 7 | "register-section": "/opt//app/javascript/register-section.jsx", 8 | "draw-section": "/opt/app/javascript/draw-section.jsx", 9 | "registration-feedback": "/opt/app/javascript/registration-feedback.jsx", 10 | "draw-feedback": "/opt/app/javascript/draw-feedback.jsx" 11 | }, 12 | "entrypoints": ["/opt/app/javascript/index.jsx"], 13 | "extensions": ["js", "jsx"], 14 | "watch": true, 15 | "minify": true, 16 | "dependencies": ["react", "react-dom"], 17 | "destination": "/opt/dist/bundle.js" 18 | } -------------------------------------------------------------------------------- /node-app/base-image/templates/dockerfile-template-slim: -------------------------------------------------------------------------------- 1 | FROM magnitus/node-app:4-slim 2 | 3 | #TODO: Set UID to whichever values makes sense 4 | ENV UID="1000" 5 | 6 | #TODO: your app content in /home/node-app/app 7 | COPY "app/*" ${APP_DIR}/ 8 | 9 | #TODO: Copy shared modules in shared modules directory 10 | # You can also simply omit the statement if you do not use shared modules 11 | COPY ["shared_modules/users", ${SHARED_DIR}/users] 12 | 13 | #TODO: Copy list of semi-colon separated npm module names that should be availabe by default everywhere in your project 14 | # You can also simply omit the declaration of this environment variable if you don't want to use any 15 | ENV NPM_MODULES="bluebird@3;xregexp@3" 16 | 17 | RUN finalize.sh 18 | 19 | USER $UID 20 | -------------------------------------------------------------------------------- /pulsar-orchestration/launch.sh: -------------------------------------------------------------------------------- 1 | ZOOKEEPER_SET="yes" 2 | if [ ! -d "./zookeeper" ]; then 3 | ZOOKEEPER_SET="no" 4 | mkdir -p zookeeper/one/data; 5 | mkdir -p zookeeper/one/datalog; 6 | mkdir -p zookeeper/two/data; 7 | mkdir -p zookeeper/two/datalog; 8 | mkdir -p zookeeper/three/data; 9 | mkdir -p zookeeper/three/datalog; 10 | fi 11 | docker-compose up -d zookeeper-one zookeeper-two zookeeper-three; 12 | sleep 10; 13 | if [ "$ZOOKEEPER_SET" = "no" ]; then 14 | ./configure_zookeeper.sh; 15 | fi 16 | 17 | if [ ! -d "./bookie" ]; then 18 | mkdir -p bookie/one/data; 19 | mkdir -p bookie/two/data; 20 | mkdir -p bookie/three/data; 21 | fi 22 | docker-compose up -d bookie-one bookie-two bookie-three; 23 | sleep 10; 24 | 25 | docker-compose up -d broker; -------------------------------------------------------------------------------- /headless-factorio-server/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3-slim 2 | 3 | ARG FACTORIO_VERSION=0.17.79 4 | ENV FACTORIO_VERSION=$FACTORIO_VERSION 5 | LABEL "factorio.version"=$FACTORIO_VERSION 6 | 7 | ENV TEMPLATES_PATH=/opt/templates 8 | ENV CONFIGS_PATH=/opt/data/configs 9 | ENV GAME_PATH=/opt/data/games 10 | 11 | RUN apt-get update && apt-get install -y wget xz-utils 12 | 13 | WORKDIR /opt 14 | 15 | RUN wget --output-document factorio.tar.xz https://factorio.com/get-download/$FACTORIO_VERSION/headless/linux64 && \ 16 | tar -xJf factorio.tar.xz && \ 17 | rm factorio.tar.xz 18 | 19 | COPY requirements.txt /opt 20 | 21 | RUN pip install -r requirements.txt 22 | 23 | COPY code /opt/code 24 | COPY templates /opt/templates 25 | 26 | WORKDIR /opt/code 27 | 28 | ENTRYPOINT ["python", "/opt/code/entrypoint.py"] -------------------------------------------------------------------------------- /ssh-encryption/image/ssh-decrypt: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ -z "$PRIVATE_KEY" ]; then 4 | echo "Private ssh key need to be defined with the PUBLIC_KEY environment variable"; 5 | exit 1; 6 | fi 7 | 8 | if [ -z "$FILE" ]; then 9 | echo "Target file need to be defined with the FILE environment variable"; 10 | exit 1; 11 | fi 12 | 13 | FILE_DIR=$(dirname $FILE) 14 | 15 | #Decrypt symmetric key with private key 16 | openssl rsautl -decrypt -inkey $PRIVATE_KEY -in $FILE_DIR/symmetric_key.encrypted -out symmetric_key; 17 | #Decrypt secret with symmetric key 18 | openssl aes-256-cbc -md sha512 -pbkdf2 -iter 100000 -salt -d -in ${FILE}.encrypted -out $FILE -pass file:symmetric_key 19 | 20 | #Cleanup decryption artifacts 21 | rm symmetric_key; 22 | rm $FILE_DIR/symmetric_key.encrypted; 23 | rm ${FILE}.encrypted; -------------------------------------------------------------------------------- /network-setup/conf: -------------------------------------------------------------------------------- 1 | fallback_dns_server: 8.8.8.8 2 | networks: 3 | test: 4 | subnet: 192.168.10.0 5 | mask: 255.255.255.0 6 | range: "192.168.10.100 192.168.10.254" 7 | router: 192.168.10.1 8 | broadcast: 192.168.10.255 9 | interface: eth0 10 | static_hosts: 11 | - mac: "00:00:00:00:00:00" 12 | ip: 192.168.10.3 13 | name: dummy_one 14 | - mac: "11:11:11:11:11:11" 15 | ip: 192.168.10.4 16 | name: dummy_two 17 | 18 | admin: 19 | subnet: 192.168.11.0 20 | mask: 255.255.255.0 21 | range: "192.168.11.100 192.168.11.254" 22 | broadcast: 192.168.11.255 23 | interface: eth1 24 | static_hosts: 25 | - mac: "00:00:00:00:00:00" 26 | ip: 192.168.11.2 27 | name: dummy_one 28 | - mac: "11:11:11:11:11:11" 29 | ip: 192.168.11.3 30 | name: dummy_two 31 | -------------------------------------------------------------------------------- /node-app/base-dev-image/code/dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:4 2 | 3 | ENV HOME_DIR /home/node-app 4 | ENV SHARED_DIR ${HOME_DIR}/shared_modules 5 | ENV APP_DIR ${HOME_DIR}/app 6 | ENV TOOL npm 7 | 8 | COPY ["finalize.sh", "/usr/local/bin/"] 9 | COPY ["resolve_dependencies.js", "/opt/app-setup/"] 10 | RUN (cd /opt/app-setup; npm install bluebird; npm install module-linker; npm install recursive-installer; npm install -g yarn) && \ 11 | chmod +x /usr/local/bin/finalize.sh && chmod +x /opt/app-setup/resolve_dependencies.js && \ 12 | mkdir ${HOME_DIR} && mkdir ${APP_DIR} && mkdir ${SHARED_DIR} && \ 13 | wget -O /usr/local/bin/dumb-init https://github.com/Yelp/dumb-init/releases/download/v1.0.2/dumb-init_1.0.2_amd64 && \ 14 | chmod +x /usr/local/bin/dumb-init 15 | 16 | WORKDIR ${APP_DIR} 17 | 18 | ENTRYPOINT ["dumb-init"] 19 | CMD ["finalize.sh"] 20 | -------------------------------------------------------------------------------- /certificate/example/self-signed-with-password/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | services: 3 | self-signed-certificate-generator: 4 | image: magnitus/certificate-generator:latest 5 | environment: 6 | COUNTRY: CA 7 | STATE: Quebec 8 | CITY: Montreal 9 | ORGANIZATION: Any 10 | DEPARTMENT: IT 11 | EMAIL: email@mydomain.com 12 | DOMAINS: dev.mydomain.com;test.mydomain.com 13 | CERTIFICATE_DURATION: 1095 14 | KEY_FILE: "" 15 | CSR_FILE: "" 16 | CERTIFICATE_FILE: "" 17 | KEY_PASSWORD_FILE: "/opt/password.txt" 18 | KEY_ENCRYPTION_CYPHER: aes256 19 | OUTPUT_CERTIFICATE_INFO: "true" 20 | volumes: 21 | - .:/opt/output 22 | - ./password.txt:/opt/password.txt 23 | -------------------------------------------------------------------------------- /headless-factorio-server/code/game.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | CONFIGS_PATH = os.environ['CONFIGS_PATH'] 4 | GAME_PATH = os.environ['GAME_PATH'] 5 | 6 | def game_defined(): 7 | return os.path.isdir(GAME_PATH) 8 | 9 | def generate_game(): 10 | os.makedirs(GAME_PATH) 11 | code = os.system( 12 | "/opt/factorio/bin/x64/factorio --create {game_path} --server-settings {server_settings_path} --map-gen-settings {map_gen_settings_path} --map-settings {map_settings_path}".format( 13 | game_path=os.path.join(GAME_PATH, 'game.zip'), 14 | server_settings_path=os.path.join(CONFIGS_PATH, 'server-settings.json'), 15 | map_gen_settings_path=os.path.join(CONFIGS_PATH, 'map-gen-settings.json'), 16 | map_settings_path=os.path.join(CONFIGS_PATH, 'map-settings.json'), 17 | ) 18 | ) 19 | if code != 0: 20 | exit(code) -------------------------------------------------------------------------------- /node-app/base-image/code/dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:4 2 | 3 | ENV HOME_DIR /home/node-app 4 | ENV SHARED_DIR ${HOME_DIR}/shared_modules 5 | ENV APP_DIR ${HOME_DIR}/app 6 | ENV NPM_COMMAND start 7 | ENV TOOL npm 8 | 9 | COPY ["finalize.sh", "/usr/local/bin/"] 10 | COPY ["resolve_dependencies.js", "/opt/app-setup/"] 11 | RUN (cd /opt/app-setup; npm install bluebird; npm install module-linker; npm install recursive-installer; npm install -g yarn) && \ 12 | chmod +x /usr/local/bin/finalize.sh && chmod +x /opt/app-setup/resolve_dependencies.js && \ 13 | mkdir ${HOME_DIR} && mkdir ${APP_DIR} && mkdir ${SHARED_DIR} && \ 14 | wget -O /usr/local/bin/dumb-init https://github.com/Yelp/dumb-init/releases/download/v1.0.2/dumb-init_1.0.2_amd64 && \ 15 | chmod +x /usr/local/bin/dumb-init 16 | 17 | WORKDIR ${APP_DIR} 18 | 19 | ENTRYPOINT ["dumb-init"] 20 | CMD ["bash", "-c", "${TOOL} run ${NPM_COMMAND}"] 21 | -------------------------------------------------------------------------------- /node-app/base-image/code/dockerfile-slim: -------------------------------------------------------------------------------- 1 | FROM node:4-slim 2 | 3 | ENV HOME_DIR /home/node-app 4 | ENV SHARED_DIR ${HOME_DIR}/shared_modules 5 | ENV APP_DIR ${HOME_DIR}/app 6 | ENV NPM_COMMAND start 7 | ENV TOOL npm 8 | 9 | COPY ["finalize.sh", "/usr/local/bin/"] 10 | COPY ["resolve_dependencies.js", "/opt/app-setup/"] 11 | RUN (cd /opt/app-setup; npm install bluebird; npm install module-linker; npm install recursive-installer; npm install -g yarn) && \ 12 | chmod +x /usr/local/bin/finalize.sh && chmod +x /opt/app-setup/resolve_dependencies.js && \ 13 | mkdir ${HOME_DIR} && mkdir ${APP_DIR} && mkdir ${SHARED_DIR} && \ 14 | wget -O /usr/local/bin/dumb-init https://github.com/Yelp/dumb-init/releases/download/v1.0.2/dumb-init_1.0.2_amd64 && \ 15 | chmod +x /usr/local/bin/dumb-init 16 | 17 | WORKDIR ${APP_DIR} 18 | 19 | ENTRYPOINT ["dumb-init"] 20 | CMD ["sh", "-c", "${TOOL} run ${NPM_COMMAND}"] 21 | -------------------------------------------------------------------------------- /sbt/README.md: -------------------------------------------------------------------------------- 1 | # Purpose 2 | 3 | This is a development image to develop scala code. 4 | 5 | I consider it a work in progress so I won't push an image for it on the foreseeable future, but you can build it on your machine. 6 | 7 | # Usage 8 | 9 | From this directory, run the following to build the image: 10 | 11 | ``` 12 | docker build -t sbt:latest . 13 | ``` 14 | 15 | Then, type the following to open an interactive shell in the containers: 16 | 17 | ``` 18 | docker run -it --rm sbt:latest bash 19 | ``` 20 | 21 | If you want to test the image with an hello world example, type the following inside the containers: 22 | 23 | ``` 24 | cd /opt 25 | sbt new scala/hello-world.g8 26 | ``` 27 | 28 | Press enter when prompted and then type the following to open an sbt console: 29 | 30 | ``` 31 | cd hello-world-template 32 | sbt 33 | ``` 34 | 35 | Then, press the following to run your hello-world example: 36 | 37 | ``` 38 | run 39 | ``` -------------------------------------------------------------------------------- /node-app/base-dev-image/code/resolve_dependencies.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const path = require('path'); 4 | const childProcess = require('child_process'); 5 | const moduleLinker = require('module-linker'); 6 | const recursiveInstaller = require('recursive-installer'); 7 | Promise = require('bluebird'); 8 | 9 | if(process.env.NPM_MODULES) 10 | { 11 | var modules = process.env.NPM_MODULES.replace(' ','').split(';'); 12 | if(modules.length > 0) 13 | { 14 | process.chdir(process.env.HOME_DIR); 15 | modules.forEach(function(module) { 16 | childProcess.execSync("npm install "+module); 17 | }); 18 | } 19 | 20 | } 21 | 22 | Promise.all([recursiveInstaller([process.env.APP_DIR, process.env.SHARED_DIR], {'maxBuffer': 5 * 1024 * 1024, 'tool': process.env.TOOL, 'lock': false}), 23 | moduleLinker([process.env.APP_DIR, process.env.SHARED_DIR], [process.env.SHARED_DIR], process.env.TOOL)]).catch((err) => { 24 | console.log(err); 25 | }) 26 | -------------------------------------------------------------------------------- /ssh-encryption/image/ssh-encrypt: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ -z "$PUBLIC_KEY" ]; then 4 | echo "Public ssh key need to be defined with the PUBLIC_KEY environment variable"; 5 | exit 1; 6 | fi 7 | 8 | if [ -z "$FILE" ]; then 9 | echo "Target file need to be defined with the FILE environment variable"; 10 | exit 1; 11 | fi 12 | 13 | FILE_DIR=$(dirname $FILE) 14 | 15 | #Change public ssh key to pem format 16 | ssh-keygen -f $PUBLIC_KEY -e -m PKCS8 > id_rsa.pem.pub; 17 | #Generate symmetric key 18 | openssl rand -out symmetric_key 32; 19 | #Encrypt file with symmetric key 20 | openssl aes-256-cbc -md sha512 -pbkdf2 -iter 100000 -salt -in $FILE -out ${FILE}.encrypted -pass file:symmetric_key; 21 | #Encrypt symmetric key with public key 22 | openssl rsautl -encrypt -pubin -inkey id_rsa.pem.pub -ssl -in symmetric_key -out $FILE_DIR/symmetric_key.encrypted; 23 | 24 | #Cleanup unencrypted secrets 25 | rm $FILE; 26 | rm symmetric_key; 27 | 28 | #Cleanup encryption artifacts 29 | rm id_rsa.pem.pub; -------------------------------------------------------------------------------- /node-app/base-image/code/resolve_dependencies.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const path = require('path'); 4 | const childProcess = require('child_process'); 5 | const moduleLinker = require('module-linker'); 6 | const recursiveInstaller = require('recursive-installer'); 7 | Promise = require('bluebird'); 8 | 9 | if(process.env.NPM_MODULES) 10 | { 11 | var modules = process.env.NPM_MODULES.replace(' ','').split(';'); 12 | if(modules.length > 0) 13 | { 14 | process.chdir(process.env.HOME_DIR); 15 | modules.forEach(function(module) { 16 | childProcess.execSync("npm install "+module); 17 | }); 18 | } 19 | 20 | } 21 | 22 | Promise.all([recursiveInstaller([process.env.APP_DIR, process.env.SHARED_DIR], {'arguments': '--production --no-lockfile', 'maxBuffer': 5 * 1024 * 1024, 'tool': process.env.TOOL}), 23 | moduleLinker([process.env.APP_DIR, process.env.SHARED_DIR], [process.env.SHARED_DIR], process.env.TOOL)]).catch((err) => { 24 | console.log(err); 25 | }) 26 | -------------------------------------------------------------------------------- /cfssl/example/ca-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "signing": { 3 | "default": { 4 | "expiry": "43800h" 5 | }, 6 | "profiles": { 7 | "server": { 8 | "expiry": "43800h", 9 | "usages": [ 10 | "signing", 11 | "key encipherment", 12 | "server auth", 13 | "client auth" 14 | ] 15 | }, 16 | "client": { 17 | "expiry": "43800h", 18 | "usages": [ 19 | "signing", 20 | "key encipherment", 21 | "client auth" 22 | ] 23 | }, 24 | "peer": { 25 | "expiry": "43800h", 26 | "usages": [ 27 | "signing", 28 | "key encipherment", 29 | "server auth", 30 | "client auth" 31 | ] 32 | } 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /node-app/image-builder/code/server/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const Hapi = require('hapi'); 4 | const Inert = require('inert'); 5 | 6 | const server = new Hapi.Server(); 7 | server.connection({ port: 8080 }); 8 | 9 | server.register(Inert, () => {}); 10 | 11 | server.route([ 12 | { 13 | method: 'GET', 14 | path: (process.env.APP_DIR+'/{param*}'), 15 | handler: { 16 | directory: { 17 | path: process.env.APP_DIR 18 | } 19 | } 20 | }, 21 | { 22 | method: 'GET', 23 | path: (process.env.SHARED_DIR+'/{param*}'), 24 | handler: { 25 | directory: { 26 | path: process.env.SHARED_DIR 27 | } 28 | } 29 | } 30 | ]); 31 | 32 | server.start((err) => { 33 | if (err) { 34 | throw err; 35 | } 36 | console.log('Server running at:', server.info.uri); 37 | }); 38 | 39 | process.on('SIGTERM', () => { 40 | console.log('Sigterm received. Terminating process...'); 41 | server.stop((err) => { 42 | process.exit(0); 43 | }); 44 | }); 45 | -------------------------------------------------------------------------------- /isc-dhcp-server/example/dhcpd.conf: -------------------------------------------------------------------------------- 1 | #In this example, we have the following setup: 2 | 3 | #We have a router on ip 192.168.2.1 4 | 5 | #The dhcp server is already running on ip 192.168.2.2 6 | 7 | #Additionally, we are running a dns server on the same host as the dhcp server 8 | 9 | #We are reserving ip range 192.168.2.3-192.168.2.19 as buffer for static ip addresses 10 | 11 | #We defined that the host whose network inteface has the mac address 00:00:00:00:00:00:00 should have the static ip 192.168.2.3 12 | 13 | #Up to 234 hosts joining the network will get an ip dynamically assigned in the 192.168.2.20-192.168.2.254 range 14 | 15 | default-lease-time 600; 16 | max-lease-time 7200; 17 | 18 | subnet 192.168.2.0 netmask 255.255.255.0 { 19 | option routers 192.168.2.1; 20 | option broadcast-address 192.168.2.255; 21 | option subnet-mask 255.255.255.0; 22 | option domain-name-servers 192.168.2.2; 23 | range 192.168.2.20 192.168.2.254; 24 | } 25 | 26 | host hera { 27 | option host-name "hera"; 28 | hardware ethernet 00:00:00:00:00:00; 29 | fixed-address 192.168.2.3; 30 | } -------------------------------------------------------------------------------- /License.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018 Eric Vallee 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /remote-terraform/ansible_scripts/plan.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Set directory to upload terraform scripts 3 | hosts: all 4 | tasks: 5 | - set_fact: remote_terraform_config_dir="{{ lookup('env','REMOTE_TERRAFORM_CONFIG_DIR') }}" 6 | 7 | - name: Set file to store terraform state 8 | hosts: all 9 | tasks: 10 | - set_fact: remote_terraform_state_dir="{{ lookup('env','REMOTE_TERRAFORM_STATE_DIR') }}" 11 | 12 | - name: Set image to execute terraform configuration from 13 | hosts: all 14 | tasks: 15 | - set_fact: remote_terraform_image="{{ lookup('env','REMOTE_TERRAFORM_IMAGE') }}" 16 | 17 | - name: Set remote container name to run terraform operation in 18 | hosts: all 19 | tasks: 20 | - set_fact: remote_container_name="{{ lookup('env','REMOTE_CONTAINER_NAME') }}" 21 | 22 | - name: Upload terraform configuration 23 | hosts: all 24 | roles: 25 | - { role: ./roles/deploy_scripts, become: true } 26 | 27 | - name: Run terraform plan 28 | hosts: all 29 | roles: 30 | - { role: ./roles/terraform_plan, become: true } 31 | 32 | - name: Cleanup terraform configuration 33 | hosts: all 34 | roles: 35 | - { role: ./roles/cleanup_scripts, become: true } -------------------------------------------------------------------------------- /remote-terraform/ansible_scripts/apply.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Set directory to upload terraform scripts 3 | hosts: all 4 | tasks: 5 | - set_fact: remote_terraform_config_dir="{{ lookup('env','REMOTE_TERRAFORM_CONFIG_DIR') }}" 6 | 7 | - name: Set file to store terraform state 8 | hosts: all 9 | tasks: 10 | - set_fact: remote_terraform_state_dir="{{ lookup('env','REMOTE_TERRAFORM_STATE_DIR') }}" 11 | 12 | - name: Set image to execute terraform configuration from 13 | hosts: all 14 | tasks: 15 | - set_fact: remote_terraform_image="{{ lookup('env','REMOTE_TERRAFORM_IMAGE') }}" 16 | 17 | - name: Set remote container name to run terraform operation in 18 | hosts: all 19 | tasks: 20 | - set_fact: remote_container_name="{{ lookup('env','REMOTE_CONTAINER_NAME') }}" 21 | 22 | - name: Upload terraform configuration 23 | hosts: all 24 | roles: 25 | - { role: ./roles/deploy_scripts, become: true } 26 | 27 | - name: Run terraform apply 28 | hosts: all 29 | roles: 30 | - { role: ./roles/terraform_apply, become: true } 31 | 32 | - name: Cleanup terraform configuration 33 | hosts: all 34 | roles: 35 | - { role: ./roles/cleanup_scripts, become: true } -------------------------------------------------------------------------------- /ssh-encryption/README.md: -------------------------------------------------------------------------------- 1 | # About 2 | 3 | This image is used to encrypt and decrypt a file using an ssh key. 4 | 5 | Sometimes, you just want to pass something encrypted over the internet and don't have an obvious secure channel to pass a secret. 6 | 7 | However, given that most developpers will already have an ssh key setup on their computer and that it is asymmetric, it can be used to encrypt data with minimum fuss without having to exchange some bootstrap secret over a potentially insecure network. 8 | 9 | One dev needs to send the other his public ssh key. If particularly paranoid, some checksum could potentially be done on the provided public ssh key. 10 | 11 | # Usage 12 | 13 | See the **example** directory for an example encrypting and decrypting a small text file. 14 | 15 | It outlines the orchestration contract (ie, expected commands and environment variables) expected by the image. 16 | 17 | Note that the encryption command will delete the source file and replace it with an encrypted file and an encrypted symmetric key. The decryption command will need both of these files. Also, for this to work, you need to map the entire directory of the plaintext file as a mapped volume for the container, not just the plaintext file. 18 | 19 | -------------------------------------------------------------------------------- /chrome/README.md: -------------------------------------------------------------------------------- 1 | # Chrome 2 | 3 | **NOTICE:** While it worked for a bit, this image has always been flacky for me. I'll work on it as time allows if I find that the image by jessfraz still fails me, but truth be told, a dockerized Chrome has always been more of a nice-to-have expiment than a priority for me. 4 | 5 | This is an adaptation of a [popular](https://github.com/jessfraz/dockerfiles/tree/master/chrome) Chrome dockerfile that was needed to make it work on my machine. 6 | 7 | I abstracted necessary runtime arguments in a docker-compose file. 8 | 9 | # Usage 10 | 11 | 1) Edit the docker-compose.yml file to convey your particular settings: 12 | 13 | - Change the _UID environment variable to reflect your particular executiong context 14 | - Change the $HOME/Downloads directory in the volumes to reflect where you want your downloads to go 15 | - Change the $HOME/.config/google-chrome directory in the volumes to reflect where you want the rest of your Chrome data (bookmarks & al.) to go 16 | - Change the mem_limit and cpuset settings to reflect the amount of memory and CPU cores you wish the Chrome container to use 17 | 18 | 2) Run 'docker-compose up' to launch Chrome 19 | 20 | 3) Run 'docker-compose rm' to cleanup your environment when done 21 | -------------------------------------------------------------------------------- /isc-dhcp-server/README.md: -------------------------------------------------------------------------------- 1 | # Overview 2 | 3 | This is just a dockerfile to run the isc dhcp server. 4 | 5 | Basically, you can plugin your configuration file, start the container on the host network and you should be set. 6 | 7 | # Usage 8 | 9 | The container can be composed with the following environment variables: 10 | 11 | - IP_VERSION: Version of the IP protocol to use (ie, 4 or 6). Note that my use case if for ip 4 so 6 has not been validated. 12 | - INTERFACE: Interface the dhcp server should bind to on the host. Defaults to eth0. 13 | - SOURCE_CONF_PATH: Path the entrypoint will expect the configuration file to be at. Defaults to /opt/dhcp/dhcpd.conf. 14 | - RUNTIME_USER: The dhcp server will be running as this user. Defaults to www-data. Note that because the dhcp daemon expects this user to exist, you'll have to extent the image if the pre-existing users in the image are unsuitable for your purpose. 15 | 16 | # Example 17 | 18 | There is an example complete with a sample configuration and docker-compose file that can easily be adapted for simple needs. 19 | 20 | # Manual Push for Arm64 21 | 22 | The image comes in both amd64 and arm64 flavors. 23 | 24 | However, to the best of my knowledge, docker hub doesn't have a builder for arm64 images currently so the arm64 version has to be pushed manually. 25 | -------------------------------------------------------------------------------- /pyspark/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM openjdk:8-slim-buster 2 | 3 | RUN apt-get update && \ 4 | apt-get install -y build-essential libssl-dev libffi-dev python3-dev && \ 5 | ln -s /usr/bin/python3 /usr/bin/python 6 | 7 | RUN apt-get install -y python3-pip && \ 8 | ln -s /usr/bin/pip3 /usr/bin/pip 9 | 10 | RUN pip install jupyter 11 | 12 | RUN apt-get update && apt-get install -y curl gnupg && \ 13 | echo "deb https://dl.bintray.com/sbt/debian/ /" > /etc/apt/sources.list.d/sbt.list && \ 14 | curl -sL "https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x2EE0EA64E40A89B84B2DF73499E82A75642AC823" | apt-key add && \ 15 | apt-get update && apt-get install -y sbt 16 | 17 | RUN pip install py4j 18 | 19 | WORKDIR /opt 20 | 21 | RUN curl http://muug.ca/mirror/apache-dist/spark/spark-2.4.5/spark-2.4.5-bin-hadoop2.7.tgz --output spark-2.4.5-bin-hadoop2.7.tgz && \ 22 | tar zxvf spark-2.4.5-bin-hadoop2.7.tgz && \ 23 | rm spark-2.4.5-bin-hadoop2.7.tgz 24 | 25 | ENV SPARK_HOME=/opt/spark-2.4.5-bin-hadoop2.7 26 | ENV PATH="/opt/spark-2.4.5-bin-hadoop2.7/bin:${PATH}" 27 | ENV PYSPARK_DRIVER_PYTHON=jupyter 28 | ENV PYSPARK_DRIVER_PYTHON_OPTS=notebook 29 | 30 | RUN cd /opt/spark-2.4.5-bin-hadoop2.7/python && python setup.py install 31 | 32 | CMD ["jupyter", "notebook", "--no-browser", "--allow-root", "--ip", "0.0.0.0"] -------------------------------------------------------------------------------- /electron-app/README.md: -------------------------------------------------------------------------------- 1 | # electron-app 2 | 3 | This is a dockerfile to launch an electron gui within a docker container. 4 | 5 | Currently, the sole image is oriented toward a dev environment where the the source code changes a lot (and is therefore in a bound volume), because it's where I'm at. 6 | 7 | I'm merely beginning my electron(ic) journey and so far this image only ran an "hello world" example, so I can't really vouch about its correctness yet, except that it can run an hello world example :). 8 | 9 | ## Usage 10 | 11 | The 'dockerfile' and 'entryScript.sh' files that I used to build the image that was pushed in the docker hub are included for completeness, but not necessary to run the image. 12 | 13 | You just need to use docker-compose to make use of the prescribed settings to launch the container. 14 | 15 | You'll want to tweak the settings (user name and id and corresponding home folder) in the docker-compose.yml file to reflect your environment and change the content of the 'app' directory with your electron app. 16 | 17 | ## Name Change Notice 18 | 19 | Changed the name (including the image) for this project from atom-electron to electron-app as I found the previous name confusing (given the existence of the Atom text editor) when revisiting the project after a prolonged absence. I'll keep the old atom-electron image on my docker hub for compatibility reason in the unlikely event that someone out there is depending on it. 20 | -------------------------------------------------------------------------------- /certificate/example/ca-signed/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | services: 3 | ca-certificate-generator: 4 | image: magnitus/certificate-generator:latest 5 | environment: 6 | COUNTRY: CA 7 | STATE: Quebec 8 | CITY: Montreal 9 | ORGANIZATION: Any 10 | DEPARTMENT: IT 11 | EMAIL: email@cadomain.com 12 | DOMAINS: dev.cadomain.com;test.cadomain.com 13 | CERTIFICATE_DURATION: 1095 14 | KEY_FILE: "ca.key" 15 | CSR_FILE: "ca.csr" 16 | CERTIFICATE_FILE: "ca.crt" 17 | OUTPUT_CERTIFICATE_INFO: "true" 18 | volumes: 19 | - .:/opt/output 20 | certificate-generator: 21 | image: magnitus/certificate-generator:latest 22 | environment: 23 | COUNTRY: CA 24 | STATE: Quebec 25 | CITY: Montreal 26 | ORGANIZATION: Any 27 | DEPARTMENT: IT 28 | EMAIL: email@mydomain.com 29 | DOMAINS: dev.mydomain.com;test.mydomain.com 30 | CERTIFICATE_DURATION: 1095 31 | KEY_FILE: "certificate.key" 32 | CSR_FILE: "certificate.csr" 33 | CERTIFICATE_FILE: "certificate.crt" 34 | CA_KEY_FILE: "/opt/output/ca.key" 35 | CA_CERTIFICATE_FILE: "/opt/output/ca.crt" 36 | OUTPUT_CERTIFICATE_INFO: "true" 37 | volumes: 38 | - .:/opt/output 39 | -------------------------------------------------------------------------------- /react-build/example/app/javascript/draw-section.jsx: -------------------------------------------------------------------------------- 1 | var React = require('react'); 2 | var ReactDOM = require('react-dom'); 3 | 4 | var DrawFeedback = require('draw-feedback'); 5 | 6 | module.exports = React.createClass({ 7 | handleSubmit: function(event) { 8 | //Sometimes, it's extra work to prevent built-in browser defaults (in this case, reloading the page), but 9 | //I think using the right semantic html tags to describe gui structure makes the application easier to understand 10 | event.preventDefault(); 11 | this.props.initiateDraw(); 12 | }, 13 | render: function() { 14 | var self = this; 15 | return ( 16 |
17 | {function() { 18 | if(this.props.winners === null) 19 | { 20 | return ( 21 |
22 |

Press Button For a Draw

23 |

Pot amount: {this.props.potAmount}

24 | 25 |
26 | ); 27 | } 28 | else 29 | { 30 | return (); 31 | } 32 | }.call(this)} 33 |
34 | ); 35 | } 36 | }); -------------------------------------------------------------------------------- /react-build/example-onbuild/app/javascript/draw-section.jsx: -------------------------------------------------------------------------------- 1 | var React = require('react'); 2 | var ReactDOM = require('react-dom'); 3 | 4 | var DrawFeedback = require('draw-feedback'); 5 | 6 | module.exports = React.createClass({ 7 | handleSubmit: function(event) { 8 | //Sometimes, it's extra work to prevent built-in browser defaults (in this case, reloading the page), but 9 | //I think using the right semantic html tags to describe gui structure makes the application easier to understand 10 | event.preventDefault(); 11 | this.props.initiateDraw(); 12 | }, 13 | render: function() { 14 | var self = this; 15 | return ( 16 |
17 | {function() { 18 | if(this.props.winners === null) 19 | { 20 | return ( 21 |
22 |

Press Button For a Draw

23 |

Pot amount: {this.props.potAmount}

24 | 25 |
26 | ); 27 | } 28 | else 29 | { 30 | return (); 31 | } 32 | }.call(this)} 33 |
34 | ); 35 | } 36 | }); -------------------------------------------------------------------------------- /react-build/example/app/javascript/registration-feedback.jsx: -------------------------------------------------------------------------------- 1 | var React = require('react'); 2 | var ReactDOM = require('react-dom'); 3 | 4 | module.exports = React.createClass({ 5 | handleInfoClick: function() { 6 | this.props.hideRegistrant(); 7 | }, 8 | render: function() { 9 | if(this.props.lastRegistrant.number != -1) 10 | { 11 | var title = "Successful Registration"; 12 | } 13 | else 14 | { 15 | var title = "Unsuccessful Registration"; 16 | } 17 | return ( 18 |
19 |

{title}

20 | {function() { 21 | if(this.props.lastRegistrant.number != -1) 22 | { 23 | return ( 24 | 25 |
26 |
Name:
27 |
{this.props.lastRegistrant.name}
28 |
Number:
29 |
{this.props.lastRegistrant.number}
30 |
31 | ); 32 | } 33 | else 34 | { 35 | return ( 36 | 37 |

Registrant already exists!

38 | ); 39 | } 40 | }.call(this)} 41 |
42 | ); 43 | } 44 | }); -------------------------------------------------------------------------------- /react-build/example-onbuild/app/javascript/registration-feedback.jsx: -------------------------------------------------------------------------------- 1 | var React = require('react'); 2 | var ReactDOM = require('react-dom'); 3 | 4 | module.exports = React.createClass({ 5 | handleInfoClick: function() { 6 | this.props.hideRegistrant(); 7 | }, 8 | render: function() { 9 | if(this.props.lastRegistrant.number != -1) 10 | { 11 | var title = "Successful Registration"; 12 | } 13 | else 14 | { 15 | var title = "Unsuccessful Registration"; 16 | } 17 | return ( 18 |
19 |

{title}

20 | {function() { 21 | if(this.props.lastRegistrant.number != -1) 22 | { 23 | return ( 24 | 25 |
26 |
Name:
27 |
{this.props.lastRegistrant.name}
28 |
Number:
29 |
{this.props.lastRegistrant.number}
30 |
31 | ); 32 | } 33 | else 34 | { 35 | return ( 36 | 37 |

Registrant already exists!

38 | ); 39 | } 40 | }.call(this)} 41 |
42 | ); 43 | } 44 | }); -------------------------------------------------------------------------------- /node-app/dockerfile-builder/README.md: -------------------------------------------------------------------------------- 1 | ##Automated Dockerfile Creation Using the dockerfile-builder Image and a Customized docker-compose.yml File Derived From the Template 2 | 3 | Take the docker-compose.yml template file and customize is for your needs (any parts between <<...>> should be customised). 4 | 5 | ###Customizations 6 | 7 | * container-name: Name of the container that builds the dockerfile (mostly useful to avoid name clashed with already running containers) 8 | * environment 9 | * UID: Running user ID of the image that will be created from the generated dockerfile 10 | * OUTPUT_UID: User ID of the outputed dockerfile and other dependent files 11 | * OUTPUT_IMAGE: Full image name of the image that will be created from the generated dockerfile 12 | * IGNORE: Regex pattern identifiying files that the dockerfile should not copy (for example, my text editor always creates backup files ending with ~ that I don't want included in a production image) 13 | * volume mapping 14 | * App directory: Change the LHS of the volume mapping to map to the directory where your app is contained 15 | * Shared directory: Change the LHS of the volume mapping to map to the directory where your local shared modules are located 16 | * Ouput directory: Change the LHS of the volume mapping to map to the directory where you would like your dockerfile, build script and other dependencies generated 17 | 18 | ###Output 19 | 20 | The dockerfile should appear in the specified output directory along with a build.sh bash script to build it. 21 | 22 | ###Examples 23 | 24 | The 'dockerfile-builder-image-example' directory contain an example, adapted to have its dockerfile automatically generated. 25 | -------------------------------------------------------------------------------- /node-app/image-builder/code/app/compileDependencies.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | const actOnModules = require('act-on-modules'); 4 | 5 | var mainKey = '!APP!'; 6 | 7 | var info = { 8 | pathsByModule: {}, 9 | dependenciesByModule: {}, 10 | resolvedDependencies: {}, 11 | dependencies: {} 12 | }; 13 | 14 | function compileInfo(directory) 15 | { 16 | var package = JSON.parse(fs.readFileSync(path.join(directory, 'package.json'), 'utf8')); 17 | var packageName = this.mainModule ? mainKey : package.name; 18 | this.pathsByModule[packageName] = directory; 19 | if(package.localDependencies) 20 | { 21 | this.dependenciesByModule[packageName] = package.localDependencies; 22 | } 23 | } 24 | 25 | function compileDependencies(currentModule, info) 26 | { 27 | if(info.resolvedDependencies[currentModule]) 28 | { 29 | return; 30 | } 31 | 32 | info.resolvedDependencies[currentModule] = true; 33 | if(info.dependenciesByModule[currentModule]) 34 | { 35 | info.dependenciesByModule[currentModule].forEach((dependency) => { 36 | info.dependencies[dependency] = true; 37 | compileDependencies(dependency, info); 38 | }); 39 | } 40 | } 41 | 42 | module.exports = function() { 43 | var compileInfoBound = compileInfo.bind(info); 44 | info.mainModule = true; 45 | actOnModules.sync(process.env.APP_DIR, compileInfoBound); 46 | info.mainModule = false; 47 | actOnModules.sync(process.env.SHARED_DIR, compileInfoBound); 48 | 49 | compileDependencies(mainKey, info); 50 | 51 | delete info['mainModule']; 52 | 53 | return info; 54 | }; 55 | 56 | -------------------------------------------------------------------------------- /node-app/dockerfile-builder/code/app/getCopySharedCmd.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | const getCopyCmd = require('./getCopyCmd'); 4 | 5 | var namesToPaths = {}; 6 | var namesToDependencies = {}; 7 | var resolvedDependencies = {}; 8 | 9 | function mapNames(rootPath) 10 | { 11 | fs.readdirSync(rootPath).forEach(function(directory) { 12 | var package = JSON.parse(fs.readFileSync(path.join(rootPath, directory, 'package.json'), 'utf8')); 13 | namesToPaths[package.name] = path.join(rootPath, directory); 14 | namesToDependencies[package.name] = package.localDependencies; 15 | }); 16 | } 17 | 18 | function dependenciesToCmds(name, destination) 19 | { 20 | if(namesToDependencies[name]) 21 | { 22 | return namesToDependencies[name].reduce((cmds, currentDep) => { 23 | if(!resolvedDependencies[currentDep]) 24 | { 25 | resolvedDependencies[currentDep] = true; 26 | var _path = namesToPaths[currentDep]; 27 | var _destination = path.join(destination, path.basename(namesToPaths[currentDep])); 28 | return cmds + "\n" + getCopyCmd(_path, _destination) + dependenciesToCmds(currentDep, destination); 29 | } 30 | }, ""); 31 | } 32 | else 33 | { 34 | return "\n"; 35 | } 36 | } 37 | 38 | module.exports = function (appDir, sharedAppDir, destinationDir) 39 | { 40 | resolvedDependencies = {}; 41 | namesToPaths = {}; 42 | namesToDependencies = {}; 43 | 44 | var package = JSON.parse(fs.readFileSync(path.join(appDir, 'package.json'), 'utf8')); 45 | namesToDependencies['[APP]'] = package.localDependencies; 46 | 47 | mapNames(sharedAppDir); 48 | return dependenciesToCmds('[APP]', destinationDir); 49 | } 50 | -------------------------------------------------------------------------------- /node-app/base-dev-image/README.md: -------------------------------------------------------------------------------- 1 | ##Development Base Image 2 | 3 | Unlike the production-oriented base image, the development image can be used as is with a joining docker-compose file without customization. 4 | 5 | Of course, customizations are possible by inheriting from the image (to add environment variable and other customizations). 6 | 7 | ###Customizations 8 | 9 | The docker-compose file should have the following settings: 10 | 11 | - UID Environment variable: Determines the user and group ID that the node app will run under in the container 12 | - NPM_COMMAND Environment Variable: Determines the command that will be passed as to "npm run" when the container launches. Defaults to "start". 13 | - NPM_MODULES environment variable: npm modules that should be globally available to code in your app (see base image documentation for greater details). 14 | - ALWAYS_INSTALL variable: Set this environment variable if you want npm install & shared module linking each time you start your container. Leaving it unset will greatly speed up re-starting the container, but will also force you to destroy and re-create the container if you change your dependencies in package.json files. 15 | - TOOL Environment Variable: Tool that you want to use to install your dependencies, link your shared modules and launch your program. Defaults to "npm". Can be set to "yarn" instead. 16 | - /home/node-app/app volume mapping: Map your main application to this path in the image (see base image documentation for greater details). 17 | - /home/node-app/shared_modules: Map your local shared modules to this path in the image (see base image documentation for greater details). 18 | 19 | ###Examples 20 | 21 | The 'example' directory contain an example with the docker-compose file already prepared. Its the same example as example 4 for the base-image, but adapted to the development image. 22 | 23 | 24 | -------------------------------------------------------------------------------- /certificate/example/ca-signed-with-password/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | services: 3 | ca-certificate-generator: 4 | image: magnitus/certificate-generator:latest 5 | environment: 6 | COUNTRY: CA 7 | STATE: Quebec 8 | CITY: Montreal 9 | ORGANIZATION: Any 10 | DEPARTMENT: IT 11 | EMAIL: email@cadomain.com 12 | DOMAINS: dev.cadomain.com;test.cadomain.com 13 | CERTIFICATE_DURATION: 1095 14 | KEY_FILE: "ca.key" 15 | CSR_FILE: "ca.csr" 16 | CERTIFICATE_FILE: "ca.crt" 17 | OUTPUT_CERTIFICATE_INFO: "true" 18 | KEY_PASSWORD_FILE: "/opt/ca-password.txt" 19 | KEY_ENCRYPTION_CYPHER: aes256 20 | volumes: 21 | - .:/opt/output 22 | - ./ca-password.txt:/opt/ca-password.txt 23 | certificate-generator: 24 | image: magnitus/certificate-generator:latest 25 | environment: 26 | COUNTRY: CA 27 | STATE: Quebec 28 | CITY: Montreal 29 | ORGANIZATION: Any 30 | DEPARTMENT: IT 31 | EMAIL: email@mydomain.com 32 | DOMAINS: dev.mydomain.com;test.mydomain.com 33 | CERTIFICATE_DURATION: 1095 34 | KEY_FILE: "certificate.key" 35 | CSR_FILE: "certificate.csr" 36 | CERTIFICATE_FILE: "certificate.crt" 37 | CA_KEY_FILE: "/opt/output/ca.key" 38 | CA_CERTIFICATE_FILE: "/opt/output/ca.crt" 39 | OUTPUT_CERTIFICATE_INFO: "true" 40 | KEY_PASSWORD_FILE: "/opt/password.txt" 41 | KEY_ENCRYPTION_CYPHER: aes256 42 | CA_KEY_PASSWORD_FILE: "/opt/ca-password.txt" 43 | volumes: 44 | - .:/opt/output 45 | - ./password.txt:/opt/password.txt 46 | - ./ca-password.txt:/opt/ca-password.txt 47 | -------------------------------------------------------------------------------- /react-build/example/lib/draw.js: -------------------------------------------------------------------------------- 1 | /* 2 | Performance note: 3 | 4 | This algorithm yields acceptable performance when the number of draws is small compared to the number of balls (ie, small number of collisions in generated results) 5 | 6 | If the number of draws is a significant proportion of the number of balls (ex: 40 picks out of 50), it may be worthwhile to consider sorting an array of balls instead. 7 | 8 | Alternatively, you could calculate the number of possible permutations, generate a result at random from 1 to that number and find out the permutation is maps to, but this may not yield a significant performance improvement (generating a random number is pretty fast) and potentially lead to ridiculously large numbers (ex:, 250 ordered balls out of 300 is a lot of permutations) 9 | 10 | A final way, that could generate the fastest performances at the cost of memory, if you want to crunch a lot of results with the same set, is to pre-compute a matrix of conditional probabilites. 11 | 12 | Again, while exploring all those possibilities would make an interesting engineering exercise, quickly finding a simple solution with acceptable performance characteristics for the kind of problems we are trying to solve is paramount. 13 | */ 14 | 15 | module.exports = function(balls, draws) { 16 | if((!balls) || balls <= 0) 17 | { 18 | throw new Error("draw:ballsBadValue"); 19 | } 20 | 21 | if((!draws) || draws <= 0 || draws > balls) 22 | { 23 | throw new Error("draw:drawsBadValue"); 24 | } 25 | 26 | var results = []; 27 | 28 | while(draws > 0) 29 | { 30 | var result = Math.floor((Math.random() * balls) + 1); 31 | if(!results.some(function(element) { 32 | return element == result; 33 | })) 34 | { 35 | results.push(result); 36 | draws--; 37 | } 38 | } 39 | 40 | return results; 41 | } -------------------------------------------------------------------------------- /react-build/example-onbuild/lib/draw.js: -------------------------------------------------------------------------------- 1 | /* 2 | Performance note: 3 | 4 | This algorithm yields acceptable performance when the number of draws is small compared to the number of balls (ie, small number of collisions in generated results) 5 | 6 | If the number of draws is a significant proportion of the number of balls (ex: 40 picks out of 50), it may be worthwhile to consider sorting an array of balls instead. 7 | 8 | Alternatively, you could calculate the number of possible permutations, generate a result at random from 1 to that number and find out the permutation is maps to, but this may not yield a significant performance improvement (generating a random number is pretty fast) and potentially lead to ridiculously large numbers (ex:, 250 ordered balls out of 300 is a lot of permutations) 9 | 10 | A final way, that could generate the fastest performances at the cost of memory, if you want to crunch a lot of results with the same set, is to pre-compute a matrix of conditional probabilites. 11 | 12 | Again, while exploring all those possibilities would make an interesting engineering exercise, quickly finding a simple solution with acceptable performance characteristics for the kind of problems we are trying to solve is paramount. 13 | */ 14 | 15 | module.exports = function(balls, draws) { 16 | if((!balls) || balls <= 0) 17 | { 18 | throw new Error("draw:ballsBadValue"); 19 | } 20 | 21 | if((!draws) || draws <= 0 || draws > balls) 22 | { 23 | throw new Error("draw:drawsBadValue"); 24 | } 25 | 26 | var results = []; 27 | 28 | while(draws > 0) 29 | { 30 | var result = Math.floor((Math.random() * balls) + 1); 31 | if(!results.some(function(element) { 32 | return element == result; 33 | })) 34 | { 35 | results.push(result); 36 | draws--; 37 | } 38 | } 39 | 40 | return results; 41 | } -------------------------------------------------------------------------------- /node-app/dockerfile-builder/code/app/index.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const fs = require('fs'); 4 | const path = require('path'); 5 | const childProcess = require('child_process'); 6 | const chownr = require('chownr'); 7 | const cpr = require('cpr'); 8 | 9 | const getCopyCmd = require('./getCopyCmd'); 10 | const getCopySharedCmd = require('./getCopySharedCmd'); 11 | 12 | //Read template in memory 13 | var output = fs.readFileSync(process.env.TEMPLATE_PATH, 'utf8'); 14 | 15 | //Plug values in template 16 | output = output.replace(/{{UID}}/, process.env.UID); 17 | output = output.replace(/{{COPY_APP}}/, getCopyCmd(process.env.APP_DIR, "${APP_DIR}")); 18 | output = output.replace(/{{COPY_SHARED}}/, getCopySharedCmd(process.env.APP_DIR, process.env.SHARED_DIR, "${SHARED_DIR}")); 19 | 20 | 21 | fs.writeFileSync(path.join(process.env.OUTPUT_DIR, 'dockerfile'), output); 22 | fs.writeFileSync(path.join(process.env.OUTPUT_DIR, 'build.sh'), "docker build -t "+process.env.OUTPUT_IMAGE+" -f dockerfile ."); 23 | 24 | cpr(process.env.APP_DIR, path.join(process.env.OUTPUT_DIR, 'app'), { 25 | deleteFirst: true, //Delete "to" before 26 | overwrite: true, //If the file exists, overwrite it 27 | confirm: true //After the copy, stat all the copied files to make sure they are there 28 | }, function(err, files) { 29 | if(err) 30 | { 31 | process.exit(1); 32 | } 33 | else 34 | { 35 | cpr(process.env.SHARED_DIR, path.join(process.env.OUTPUT_DIR, 'shared'), { 36 | deleteFirst: true, //Delete "to" before 37 | overwrite: true, //If the file exists, overwrite it 38 | confirm: true //After the copy, stat all the copied files to make sure they are there 39 | }, function(err, files) { 40 | if(err) 41 | { 42 | process.exit(1); 43 | } 44 | chownr.sync(process.env.OUTPUT_DIR, parseInt(process.env.OUTPUT_UID), parseInt(process.env.OUTPUT_UID)); 45 | }); 46 | } 47 | }); 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /node-app/image-builder/code/app/wgetDirCmd.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | 4 | var ignoreRegex = process.env.IGNORE ? new RegExp(process.env.IGNORE) : null; 5 | 6 | function wgetDirCmd(rootPath, destination , trimToDestination, prefix) 7 | { 8 | //Plug app copy in template 9 | var cmd = prefix ? prefix : ""; 10 | var addedOne = false; 11 | var acceptExtensionFlag = ""; 12 | 13 | fs.readdirSync(rootPath).forEach((filename) => { 14 | if(filename != "node_modules" && (ignoreRegex && (!ignoreRegex.test(filename)))) 15 | { 16 | if(fs.lstatSync(path.join(rootPath, filename)).isDirectory()) 17 | { 18 | var cmdForDir = wgetDirCmd(path.join(rootPath, filename), destination, trimToDestination, ""); 19 | if(cmdForDir != "") 20 | { 21 | if((!addedOne)) 22 | { 23 | addedOne = true; 24 | cmd += " "; 25 | } 26 | else 27 | { 28 | cmd += " && "; 29 | } 30 | cmd += cmdForDir; 31 | } 32 | } 33 | else 34 | { 35 | if(!addedOne) 36 | { 37 | addedOne = true; 38 | 39 | } 40 | else 41 | { 42 | cmd += " && "; 43 | } 44 | 45 | acceptExtensionFlag = path.extname(filename) != '' ? '-A'+path.extname(filename) : ''; 46 | 47 | cmd += ("mkdir -p "+rootPath.replace(trimToDestination, destination)+" && wget 'http://"+process.env.DOCKER_LOCALHOST+":"+process.env.EXTERNAL_PORT+path.join(rootPath, filename) + "' --output-document=\"" + path.join(destination, path.join(rootPath, filename).replace(trimToDestination+"/", ""))+"\""); 48 | } 49 | } 50 | }); 51 | 52 | return cmd; 53 | } 54 | 55 | module.exports = wgetDirCmd; 56 | -------------------------------------------------------------------------------- /cfssl/README.md: -------------------------------------------------------------------------------- 1 | # Purpose 2 | 3 | Docker images for the cfssl project: https://github.com/cloudflare/cfssl 4 | 5 | As I need cfssl to run on arm64 machines and the official binary are not (at the time of this writing) running properly on Scaleway arm64 machines, I opted to create my own arm64 image and also decided to make an amd64 version while I was at it. 6 | 7 | # Usage 8 | 9 | ## Images Names 10 | 11 | The image for adm64 is **magnitus/cfssl:latest**. The image for arm64 is **magnitus/cfssl:arm64-latest** 12 | 13 | ## Included Binaries 14 | 15 | The **cfssl** and **cfssljson** were built into the images 16 | 17 | ## Running It 18 | 19 | By default, the execution directory is **/opt** and the command is **sh** (no entrypoint). 20 | 21 | You can override the command, setting it run either **cfssl** or **cfssljson** with whatever arguments you need. You can also map whichever directory should provide files input or receive files output to the container. 22 | 23 | Take the following command as an example: 24 | 25 | ``` 26 | cfssl gencert -initca ca-csr.json | cfssljson -bare ca - 27 | cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=client client.json | cfssljson -bare client 28 | ``` 29 | 30 | You would run it this way with the docker images: 31 | 32 | ``` 33 | IMAGE=magnitus/cfssl:latest 34 | docker run --rm -v $(pwd):/opt $IMAGE cfssl gencert -initca ca-csr.json \ 35 | | docker run --rm -i -v $(pwd):/opt $IMAGE cfssljson -bare ca - 36 | docker run --rm -v $(pwd):/opt $IMAGE cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=client client.json \ 37 | | docker run --rm -i -v $(pwd):/opt $IMAGE cfssljson -bare client - 38 | ``` 39 | 40 | All the dependent files for the example can be found in the **example** directory. 41 | 42 | # Manual Push 43 | 44 | Because I don't think Docker Hub supports arm64 automated builds at this time, the arm64 images have to be pushed manually (ie, no automated build). If you want to use the images, but don't really trust the source (I totally get it), feel free to clone the repo and build your own from the project's Dockerfiles (keeping in mind that you'll need an arm64 machine to build the arm64 images). -------------------------------------------------------------------------------- /react-build/example/app/javascript/draw-feedback.jsx: -------------------------------------------------------------------------------- 1 | var React = require('react'); 2 | var ReactDOM = require('react-dom'); 3 | 4 | function getRankingSuffix(rank) 5 | { 6 | if(rank == 1) 7 | { 8 | return 'rst'; 9 | } 10 | else if(rank == 2) 11 | { 12 | return 'nd'; 13 | } 14 | else if(rank == 3) 15 | { 16 | return 'rd'; 17 | } 18 | else 19 | { 20 | return 'th'; 21 | } 22 | } 23 | 24 | var WinnersList = React.createClass({ 25 | render: function() { 26 | return ( 27 |
    28 | {this.props.winners.map(function(winner, index){ 29 | if(winner === null) 30 | { 31 | return ( 32 |
  • 33 | {(index+1)+getRankingSuffix(index+1)+' ball'} 34 | {'no winner'} 35 |
  • 36 | ); 37 | } 38 | else 39 | { 40 | return ( 41 |
  • 42 | {(index+1)+getRankingSuffix(index+1)+' ball'} 43 | {winner['name']+': '+winner['award']+ '$'} 44 |
  • 45 | ); 46 | } 47 | })} 48 |
49 | ); 50 | } 51 | }); 52 | 53 | 54 | module.exports = React.createClass({ 55 | handleClick: function(event) { 56 | this.props.clearParticipants(); 57 | }, 58 | render: function() { 59 | var allNull = this.props.winners.every(function(elem) {return elem === null}); 60 | var content = []; 61 | content.push(

Winners

); 62 | if(allNull) 63 | { 64 | content.push(

No winners this round. Better luck next time...

); 65 | } 66 | else 67 | { 68 | content.push(); 69 | } 70 | return ( 71 | 72 |
{content}
73 | ); 74 | } 75 | }); -------------------------------------------------------------------------------- /react-build/example-onbuild/app/javascript/draw-feedback.jsx: -------------------------------------------------------------------------------- 1 | var React = require('react'); 2 | var ReactDOM = require('react-dom'); 3 | 4 | function getRankingSuffix(rank) 5 | { 6 | if(rank == 1) 7 | { 8 | return 'rst'; 9 | } 10 | else if(rank == 2) 11 | { 12 | return 'nd'; 13 | } 14 | else if(rank == 3) 15 | { 16 | return 'rd'; 17 | } 18 | else 19 | { 20 | return 'th'; 21 | } 22 | } 23 | 24 | var WinnersList = React.createClass({ 25 | render: function() { 26 | return ( 27 |
    28 | {this.props.winners.map(function(winner, index){ 29 | if(winner === null) 30 | { 31 | return ( 32 |
  • 33 | {(index+1)+getRankingSuffix(index+1)+' ball'} 34 | {'no winner'} 35 |
  • 36 | ); 37 | } 38 | else 39 | { 40 | return ( 41 |
  • 42 | {(index+1)+getRankingSuffix(index+1)+' ball'} 43 | {winner['name']+': '+winner['award']+ '$'} 44 |
  • 45 | ); 46 | } 47 | })} 48 |
49 | ); 50 | } 51 | }); 52 | 53 | 54 | module.exports = React.createClass({ 55 | handleClick: function(event) { 56 | this.props.clearParticipants(); 57 | }, 58 | render: function() { 59 | var allNull = this.props.winners.every(function(elem) {return elem === null}); 60 | var content = []; 61 | content.push(

Winners

); 62 | if(allNull) 63 | { 64 | content.push(

No winners this round. Better luck next time...

); 65 | } 66 | else 67 | { 68 | content.push(); 69 | } 70 | return ( 71 | 72 |
{content}
73 | ); 74 | } 75 | }); -------------------------------------------------------------------------------- /node-app/image-builder/code/app/index.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const fs = require('fs'); 4 | const path = require('path'); 5 | const childProcess = require('child_process'); 6 | 7 | const dependencies = (require('./compileDependencies')()); 8 | const wgetDirCmd = require('./wgetDirCmd'); 9 | 10 | var exitCode = 0; 11 | 12 | var source_image = process.env.SOURCE_IMAGE ? process.env.SOURCE_IMAGE : process.env.DEFAULT_SOURCE_IMAGE; 13 | 14 | //Read template in memory 15 | var output = fs.readFileSync(process.env.TEMPLATE_PATH, 'utf8'); 16 | 17 | output = output.replace(/{{SOURCE}}/, source_image); 18 | 19 | //Plug values in template 20 | output = output.replace(/{{UID}}/, process.env.UID); 21 | 22 | output = process.env.NPM_COMMAND ? output.replace(/{{NPM_COMMAND}}/, "ENV NPM_COMMAND "+process.env.NPM_COMMAND) : output.replace(/{{NPM_COMMAND}}/, ""); 23 | 24 | var wgetFilesCmd = wgetDirCmd(process.env.APP_DIR, "${APP_DIR}", process.env.APP_DIR, "RUN "); 25 | 26 | try 27 | { 28 | fs.accessSync(process.env.SHARED_DIR, fs.F_OK); 29 | Object.keys(dependencies['dependencies']).forEach((module) => { 30 | wgetFilesCmd = wgetFilesCmd + wgetDirCmd(dependencies['pathsByModule'][module], "${SHARED_DIR}", process.env.SHARED_DIR, " && "); 31 | }); 32 | } 33 | catch(err) 34 | { 35 | } 36 | 37 | output = output.replace(/{{COPY_ALL}}/, wgetFilesCmd); 38 | 39 | console.log("Building image \""+process.env.OUTPUT_IMAGE+"\" with the following dockerfile: ") 40 | console.log("*********************************"); 41 | console.log(output); 42 | console.log("*********************************"); 43 | 44 | const serverProcess = childProcess.spawn('npm', ['start'], {'cwd': process.env.SERVER_DIR}); 45 | 46 | serverProcess.on('exit', (code) => { 47 | process.exit(exitCode); 48 | }); 49 | 50 | if(process.env.CACHE == 'yes') 51 | { 52 | var buildArgs = ['build', '-t', process.env.OUTPUT_IMAGE, '-']; 53 | } 54 | else 55 | { 56 | var buildArgs = ['build', '--no-cache', '-t', process.env.OUTPUT_IMAGE, '-'] 57 | } 58 | 59 | 60 | const buildProcess = childProcess.spawn('docker', buildArgs, {'cwd': '/opt'}); 61 | 62 | buildProcess.stdout.pipe(process.stdout); 63 | buildProcess.stderr.pipe(process.stderr); 64 | 65 | buildProcess.on('exit', (code) => { 66 | exitCode = code; 67 | serverProcess.kill('SIGTERM'); 68 | }); 69 | 70 | buildProcess.stdin.write(output); 71 | buildProcess.stdin.end(); 72 | -------------------------------------------------------------------------------- /network-setup/README.md: -------------------------------------------------------------------------------- 1 | # Purpose 2 | 3 | This container sets up dockerized dhcp and dns servers on a networked machine based on a configuration file. 4 | 5 | The following manual tasks still needs to be done before running this container: 6 | - Setup the routing 7 | - Setup a static ip on the network interfaces of the machine hosting the dhcp/dns containers 8 | - Potentially disable existing services that are already listening on port 53 on the machine (https://askubuntu.com/questions/907246/how-to-disable-systemd-resolved-in-ubuntu) 9 | - As a result of the above step, you might have to add your local hostname to the **/etc/hosts** file and add your localhost to **/etc/resolv.conf** (other machines on the network should not require those steps) 10 | 11 | From there, assuming your configuration is comprehensive, ip and name assignment will be handled from a centralized configuration file on the machine running the dhcp/dns servers. 12 | 13 | This should work well in a network where the number of machines that need to have a fixed ip and known name is limited to at most ~20 machines (ex: home lab, small company, etc). 14 | 15 | In a larger setup, a dynamic system where machines requiring a fixed ip and a known name register themselves probably makes more sense. 16 | 17 | # Usage 18 | 19 | Change the content of the "conf" file for something that makes sense for your network. 20 | 21 | The top-level entries under "networks" are the various networks the dhcp/dns server will server. The name of each entry represents the domain name that will be used on the network. 22 | 23 | For example, if the entry is test, then a host with the name **hosta** will actually be have the name **hosta.test**. 24 | 25 | The machines list is optional. If set, it will make sure that for each mac address specifie, the given machine will have to given ip and name (remember that the network domain name will be appended to that name to form the machine name). 26 | 27 | Then, run: 28 | 29 | ``` 30 | docker-compose run setup 31 | ``` 32 | # Idempotency of the scripts 33 | 34 | You can regenerate the containers with configuration file changes by re-executing the docker-compose command. 35 | 36 | There will be brief moment where the services will be unresponsive if you do this however. 37 | 38 | While I know that CoreDNS supports graceful restart with new configurations, I'm less certain the isc dhcp supports it making the point of a gracefully restart moot. 39 | 40 | The most graceful solution to conteract this may be to setup failover dhcp servers (https://kb.isc.org/docs/aa-00502). -------------------------------------------------------------------------------- /remote-terraform/ansible_scripts/roles/terraform_plan/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - name: Run terraform init on the remote machine 2 | docker_container: 3 | image: "{{ remote_terraform_image }}" 4 | name: "{{ remote_container_name }}" 5 | network_mode: host 6 | volumes: 7 | - "{{ remote_terraform_config_dir }}:/opt/terraform_config" 8 | - "{{ remote_terraform_state_dir }}:/opt/terraform_state" 9 | working_dir: "/opt/terraform_config" 10 | detach: false 11 | recreate: true 12 | state: started 13 | entrypoint: "" 14 | command: "terraform init" 15 | register: init_output 16 | 17 | - name: Get init output 18 | debug: 19 | msg: "{{ init_output.ansible_facts.docker_container.Output }}" 20 | 21 | - name: Cleanup terraform init on the remote machine 22 | docker_container: 23 | image: "{{ remote_terraform_image }}" 24 | name: "{{ remote_container_name }}" 25 | network_mode: host 26 | volumes: 27 | - "{{ remote_terraform_config_dir }}:/opt/terraform_config" 28 | - "{{ remote_terraform_state_dir }}:/opt/terraform_state" 29 | working_dir: "/opt/terraform_config" 30 | detach: false 31 | recreate: true 32 | state: started 33 | entrypoint: "" 34 | command: "terraform init" 35 | state: absent 36 | 37 | - name: Run terraform plan on the remote machine 38 | docker_container: 39 | image: "{{ remote_terraform_image }}" 40 | name: "{{ remote_container_name }}" 41 | network_mode: host 42 | volumes: 43 | - "{{ remote_terraform_config_dir }}:/opt/terraform_config" 44 | - "{{ remote_terraform_state_dir }}:/opt/terraform_state" 45 | working_dir: "/opt/terraform_config" 46 | detach: false 47 | recreate: true 48 | state: started 49 | entrypoint: "" 50 | command: "terraform plan -state /opt/terraform_state/terraform.tfstate" 51 | register: plan_output 52 | 53 | - name: Get plan output 54 | debug: 55 | msg: "{{ plan_output.ansible_facts.docker_container.Output }}" 56 | 57 | - name: Cleanup terraform plan on the remote machine 58 | docker_container: 59 | image: "{{ remote_terraform_image }}" 60 | name: "{{ remote_container_name }}" 61 | network_mode: host 62 | volumes: 63 | - "{{ remote_terraform_config_dir }}:/opt/terraform_config" 64 | - "{{ remote_terraform_state_dir }}:/opt/terraform_state" 65 | working_dir: "/opt/terraform_config" 66 | detach: false 67 | recreate: true 68 | state: started 69 | entrypoint: "" 70 | command: "terraform plan -state /opt/terraform_state/terraform.tfstate" 71 | state: absent -------------------------------------------------------------------------------- /remote-terraform/ansible_scripts/roles/terraform_apply/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - name: Run terraform init on the remote machine 2 | docker_container: 3 | image: "{{ remote_terraform_image }}" 4 | name: "{{ remote_container_name }}" 5 | network_mode: host 6 | volumes: 7 | - "{{ remote_terraform_config_dir }}:/opt/terraform_config" 8 | - "{{ remote_terraform_state_dir }}:/opt/terraform_state" 9 | working_dir: "/opt/terraform_config" 10 | detach: false 11 | recreate: true 12 | state: started 13 | entrypoint: "" 14 | command: "terraform init" 15 | register: init_output 16 | 17 | - name: Get init output 18 | debug: 19 | msg: "{{ init_output.ansible_facts.docker_container.Output }}" 20 | 21 | - name: Cleanup terraform init on the remote machine 22 | docker_container: 23 | image: "{{ remote_terraform_image }}" 24 | name: "{{ remote_container_name }}" 25 | network_mode: host 26 | volumes: 27 | - "{{ remote_terraform_config_dir }}:/opt/terraform_config" 28 | - "{{ remote_terraform_state_dir }}:/opt/terraform_state" 29 | working_dir: "/opt/terraform_config" 30 | detach: false 31 | recreate: true 32 | state: started 33 | entrypoint: "" 34 | command: "terraform init" 35 | state: absent 36 | 37 | - name: Run terraform apply on the remote machine 38 | docker_container: 39 | image: "{{ remote_terraform_image }}" 40 | name: "{{ remote_container_name }}" 41 | network_mode: host 42 | volumes: 43 | - "{{ remote_terraform_config_dir }}:/opt/terraform_config" 44 | - "{{ remote_terraform_state_dir }}:/opt/terraform_state" 45 | working_dir: "/opt/terraform_config" 46 | detach: false 47 | recreate: true 48 | state: started 49 | entrypoint: "" 50 | command: "terraform apply -auto-approve -state /opt/terraform_state/terraform.tfstate" 51 | register: apply_output 52 | 53 | - name: Get apply output 54 | debug: 55 | msg: "{{ apply_output.ansible_facts.docker_container.Output }}" 56 | 57 | - name: Cleanup terraform apply on the remote machine 58 | docker_container: 59 | image: "{{ remote_terraform_image }}" 60 | name: "{{ remote_container_name }}" 61 | network_mode: host 62 | volumes: 63 | - "{{ remote_terraform_config_dir }}:/opt/terraform_config" 64 | - "{{ remote_terraform_state_dir }}:/opt/terraform_state" 65 | working_dir: "/opt/terraform_config" 66 | detach: false 67 | recreate: true 68 | state: started 69 | entrypoint: "" 70 | command: "terraform apply -auto-approve -state /opt/terraform_state/terraform.tfstate" 71 | state: absent -------------------------------------------------------------------------------- /react-build/example/app/javascript/register-section.jsx: -------------------------------------------------------------------------------- 1 | var React = require('react'); 2 | var ReactDOM = require('react-dom'); 3 | 4 | var RegistrationFeedback = require('registration-feedback'); 5 | 6 | module.exports = React.createClass({ 7 | handleNameChange: function(event) { 8 | this.name = event.target.value; 9 | }, 10 | handleSubmit: function(event) { 11 | //Sometimes, it's extra work to prevent built-in browser defaults (in this case, reloading the page), but 12 | //I think using the right semantic html tags to describe gui structure makes the application easier to understand 13 | event.preventDefault(); 14 | if(this.name != "") 15 | { 16 | this.props.addRegistrant(this.name); 17 | document.getElementById('registrationForm').reset(); 18 | this.name = ""; 19 | } 20 | }, 21 | render: function() { 22 | if(this.props.winners === null) 23 | { 24 | return ( 25 |
26 | {function() { 27 | if(this.props.participants.length < this.props.balls) 28 | { 29 | return ( 30 |
31 |

Registration Form

32 | 33 | 34 | 35 |
36 | ); 37 | 38 | } 39 | else 40 | { 41 | return (

Fully booked. No more registrations!

); 42 | } 43 | }.call(this)} 44 | {function() { 45 | if(this.props.lastRegistrant && this.props.lastRegistrant.visible) 46 | { 47 | return ( 48 | 49 | ); 50 | } 51 | }.call(this)} 52 |
53 | ); 54 | } 55 | else 56 | { 57 | return false; 58 | } 59 | } 60 | }); -------------------------------------------------------------------------------- /react-build/example-onbuild/app/javascript/register-section.jsx: -------------------------------------------------------------------------------- 1 | var React = require('react'); 2 | var ReactDOM = require('react-dom'); 3 | 4 | var RegistrationFeedback = require('registration-feedback'); 5 | 6 | module.exports = React.createClass({ 7 | handleNameChange: function(event) { 8 | this.name = event.target.value; 9 | }, 10 | handleSubmit: function(event) { 11 | //Sometimes, it's extra work to prevent built-in browser defaults (in this case, reloading the page), but 12 | //I think using the right semantic html tags to describe gui structure makes the application easier to understand 13 | event.preventDefault(); 14 | if(this.name != "") 15 | { 16 | this.props.addRegistrant(this.name); 17 | document.getElementById('registrationForm').reset(); 18 | this.name = ""; 19 | } 20 | }, 21 | render: function() { 22 | if(this.props.winners === null) 23 | { 24 | return ( 25 |
26 | {function() { 27 | if(this.props.participants.length < this.props.balls) 28 | { 29 | return ( 30 |
31 |

Registration Form

32 | 33 | 34 | 35 |
36 | ); 37 | 38 | } 39 | else 40 | { 41 | return (

Fully booked. No more registrations!

); 42 | } 43 | }.call(this)} 44 | {function() { 45 | if(this.props.lastRegistrant && this.props.lastRegistrant.visible) 46 | { 47 | return ( 48 | 49 | ); 50 | } 51 | }.call(this)} 52 |
53 | ); 54 | } 55 | else 56 | { 57 | return false; 58 | } 59 | } 60 | }); -------------------------------------------------------------------------------- /pulsar-orchestration/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.5' 2 | services: 3 | zookeeper-one: 4 | image: zookeeper:3.6 5 | restart: always 6 | hostname: zookeeper-one 7 | volumes: 8 | - "./zookeeper/one/data:/data" 9 | - "./zookeeper/one/datalog:/datalog" 10 | - "./zookeeper-conf/zoo.cfg:/conf/zoo.cfg" 11 | environment: 12 | ZOO_CONF_DIR: /conf 13 | ZOO_MY_ID: 1 14 | networks: 15 | - pulsar-internal 16 | zookeeper-two: 17 | image: zookeeper:3.6 18 | restart: always 19 | hostname: zookeeper-two 20 | volumes: 21 | - "./zookeeper/two/data:/data" 22 | - "./zookeeper/two/datalog:/datalog" 23 | - "./zookeeper-conf/zoo.cfg:/conf/zoo.cfg" 24 | environment: 25 | ZOO_CONF_DIR: /conf 26 | ZOO_MY_ID: 2 27 | networks: 28 | - pulsar-internal 29 | zookeeper-three: 30 | image: zookeeper:3.6 31 | restart: always 32 | hostname: zookeeper-three 33 | volumes: 34 | - "./zookeeper/three/data:/data" 35 | - "./zookeeper/three/datalog:/datalog" 36 | - "./zookeeper-conf/zoo.cfg:/conf/zoo.cfg" 37 | environment: 38 | ZOO_CONF_DIR: /conf 39 | ZOO_MY_ID: 3 40 | networks: 41 | - pulsar-internal 42 | bookie-one: 43 | image: apachepulsar/pulsar:2.5.1 44 | restart: always 45 | volumes: 46 | - "./bookkeeper-conf/bookkeeper.conf:/pulsar/conf/bookkeeper.conf" 47 | - "./bookie/one/data:/pulsar/data" 48 | command: ["bin/bookkeeper", "bookie"] 49 | networks: 50 | - pulsar-internal 51 | bookie-two: 52 | image: apachepulsar/pulsar:2.5.1 53 | restart: always 54 | volumes: 55 | - "./bookkeeper-conf/bookkeeper.conf:/pulsar/conf/bookkeeper.conf" 56 | - "./bookie/two/data:/pulsar/data" 57 | command: ["bin/bookkeeper", "bookie"] 58 | networks: 59 | - pulsar-internal 60 | bookie-three: 61 | image: apachepulsar/pulsar:2.5.1 62 | restart: always 63 | volumes: 64 | - "./bookkeeper-conf/bookkeeper.conf:/pulsar/conf/bookkeeper.conf" 65 | - "./bookie/three/data:/pulsar/data" 66 | command: ["bin/bookkeeper", "bookie"] 67 | networks: 68 | - pulsar-internal 69 | broker: 70 | image: apachepulsar/pulsar:2.5.1 71 | #Will technically be ignored with scripts in non-swarm mode, but this conveys the idea. 72 | #This is cattle. 73 | deploy: 74 | replicas: 3 75 | restart: always 76 | volumes: 77 | - "./broker-conf/broker.conf:/pulsar/conf/broker.conf" 78 | command: ["bin/pulsar", "broker"] 79 | networks: 80 | - pulsar 81 | - pulsar-internal 82 | 83 | networks: 84 | pulsar: 85 | name: pulsar 86 | pulsar-internal: 87 | name: pulsar-internal -------------------------------------------------------------------------------- /headless-factorio-server/code/entrypoint.py: -------------------------------------------------------------------------------- 1 | import os 2 | import subprocess 3 | import time 4 | import signal 5 | from configs import configs_defined, generate_configs 6 | from game import game_defined, generate_game 7 | 8 | CONFIGS_PATH = os.environ['CONFIGS_PATH'] 9 | GAME_PATH = os.environ['GAME_PATH'] 10 | 11 | ADMIN_PLAYERS_CONFIG = os.path.join(CONFIGS_PATH, 'server-adminlist.json') 12 | WHITELISTED_PLAYERS_CONFIG = os.path.join(CONFIGS_PATH, 'server-whitelist.json') 13 | 14 | 15 | class ProcessSignals: 16 | exiting = False 17 | def __init__(self): 18 | signal.signal(signal.SIGINT, self.exit) 19 | signal.signal(signal.SIGTERM, self.exit) 20 | 21 | def exit(self, *args, **kwargs): 22 | self.exiting = True 23 | 24 | if __name__ == '__main__': 25 | if not configs_defined(): 26 | generate_configs() 27 | if not game_defined(): 28 | generate_game() 29 | 30 | game_path=os.path.join(GAME_PATH, 'game.zip') 31 | server_settings_path=os.path.join(CONFIGS_PATH, 'server-settings.json') 32 | map_gen_settings_path=os.path.join(CONFIGS_PATH, 'map-gen-settings.json') 33 | map_settings_path=os.path.join(CONFIGS_PATH, 'map-settings.json') 34 | command = [ 35 | "/opt/factorio/bin/x64/factorio", 36 | "--start-server", 37 | "{game_path}".format(game_path=game_path), 38 | "--server-settings", 39 | "{server_settings_path}".format(server_settings_path=server_settings_path), 40 | "--map-gen-settings", 41 | "{map_gen_settings_path}".format(map_gen_settings_path=map_gen_settings_path), 42 | "--map-settings", 43 | "{map_settings_path}".format(map_settings_path=map_settings_path), 44 | "--port", 45 | "{bind_port}".format(bind_port=os.environ['BIND_PORT']), 46 | "--bind", 47 | "{bind_ip}".format(bind_ip=os.environ['BIND_IP']) 48 | ] 49 | if os.path.isfile(WHITELISTED_PLAYERS_CONFIG): 50 | command = command + ["--use-server-whitelist", "--server-whitelist", "{whitelist_path}".format(whitelist_path=WHITELISTED_PLAYERS_CONFIG)] 51 | if os.path.isfile(ADMIN_PLAYERS_CONFIG): 52 | command = command + ["--server-adminlist", "{admin_path}".format(admin_path=ADMIN_PLAYERS_CONFIG)] 53 | 54 | process = subprocess.Popen( 55 | command, 56 | stdin=subprocess.PIPE 57 | ) 58 | process_pid = process.pid 59 | 60 | #Working around the fact that the Factorio server doesn't handle EOF on input well 61 | signal_handler = ProcessSignals() 62 | while not signal_handler.exiting: 63 | time.sleep(1) 64 | os.killpg(os.getpgid(process.pid), signal.SIGTERM) 65 | 66 | while True: 67 | try: 68 | os.kill(process_pid, 0) 69 | except OSError: 70 | break -------------------------------------------------------------------------------- /pulsar-orchestration/bookkeeper-conf/bookkeeper.conf: -------------------------------------------------------------------------------- 1 | #Taken from recommended bookkeeper configuration file with minimal adjustments 2 | bookiePort=3181 3 | journalDirectory=data/bookkeeper/journal 4 | minUsableSizeForIndexFileCreation=1073741824 5 | advertisedAddress= 6 | allowLoopback=false 7 | bookieDeathWatchInterval=1000 8 | flushInterval=60000 9 | useHostNameAsBookieID=false 10 | gcWaitTime=900000 11 | gcOverreplicatedLedgerWaitTime=86400000 12 | numAddWorkerThreads=0 13 | numReadWorkerThreads=8 14 | numHighPriorityWorkerThreads=8 15 | maxPendingReadRequestsPerThread=2500 16 | maxPendingAddRequestsPerThread=10000 17 | auditorPeriodicBookieCheckInterval=86400 18 | rereplicationEntryBatchSize=100 19 | openLedgerRereplicationGracePeriod=30 20 | autoRecoveryDaemonEnabled=true 21 | lostBookieRecoveryDelay=0 22 | serverTcpNoDelay=true 23 | journalFormatVersionToWrite=5 24 | journalMaxSizeMB=2048 25 | journalMaxBackups=5 26 | journalPreAllocSizeMB=16 27 | journalWriteBufferSizeKB=64 28 | journalRemoveFromPageCache=true 29 | journalSyncData=true 30 | journalAdaptiveGroupWrites=true 31 | journalMaxGroupWaitMSec=1 32 | journalBufferedWritesThreshold=524288 33 | numJournalCallbackThreads=8 34 | journalAlignmentSize=4096 35 | journalFlushWhenQueueEmpty=false 36 | ledgerStorageClass=org.apache.bookkeeper.bookie.storage.ldb.DbLedgerStorage 37 | ledgerDirectories=data/bookkeeper/ledgers 38 | auditorPeriodicCheckInterval=604800 39 | openFileLimit=0 40 | fileInfoFormatVersionToWrite=0 41 | pageLimit=0 42 | zkLedgersRootPath=/ledgers 43 | logSizeLimit=1073741824 44 | entryLogFilePreallocationEnabled=true 45 | readBufferSizeBytes=4096 46 | writeBufferSizeBytes=65536 47 | compactionRate=1000 48 | minorCompactionThreshold=0.2 49 | minorCompactionInterval=3600 50 | compactionMaxOutstandingRequests=100000 51 | majorCompactionThreshold=0.5 52 | majorCompactionInterval=86400 53 | isThrottleByBytes=false 54 | compactionRateByEntries=1000 55 | compactionRateByBytes=1000000 56 | statsProviderClass=org.apache.bookkeeper.stats.prometheus.PrometheusMetricsProvider 57 | prometheusStatsHttpPort=8000 58 | readOnlyModeEnabled=true 59 | diskUsageThreshold=0.95 60 | diskCheckInterval=10000 61 | zkServers=zookeeper-one:2181,zookeeper-two:2181,zookeeper-three:2181 62 | zkTimeout=30000 63 | zkEnableSecurity=false 64 | httpServerEnabled=false 65 | httpServerPort=8000 66 | httpServerClass=org.apache.bookkeeper.http.vertx.VertxHttpServer 67 | dbStorage_writeCacheMaxSizeMb=512 68 | dbStorage_readAheadCacheMaxSizeMb=256 69 | dbStorage_readAheadCacheBatchSize=1000 70 | dbStorage_rocksDB_blockCacheSize=268435456 71 | dbStorage_rocksDB_writeBufferSizeMB=64 72 | dbStorage_rocksDB_sstSizeInMB=64 73 | dbStorage_rocksDB_blockSize=65536 74 | dbStorage_rocksDB_bloomFilterBitsPerKey=10 75 | dbStorage_rocksDB_numLevels=-1 76 | dbStorage_rocksDB_numFilesInLevel0=4 77 | dbStorage_rocksDB_maxSizeInLevel1MB=256 78 | extraServerComponents=org.apache.bookkeeper.stream.server.StreamStorageLifecycleComponent -------------------------------------------------------------------------------- /certificate/test/run.py: -------------------------------------------------------------------------------- 1 | import unittest, shutil, os, subprocess, hashlib, re 2 | 3 | class TestCAWithPassword(unittest.TestCase): 4 | def setUp(self): 5 | shutil.copytree(os.path.join('..', 'example', 'ca-signed-with-password'), os.path.join('.', 'certificate')) 6 | subprocess.check_call("docker-compose up ca-certificate-generator", shell=True, cwd=os.path.join('.', 'certificate')) 7 | subprocess.check_call("docker-compose up certificate-generator", shell=True, cwd=os.path.join('.', 'certificate')) 8 | 9 | def tearDown(self): 10 | subprocess.check_call("docker-compose down", shell=True, cwd=os.path.join('.', 'certificate')) 11 | shutil.rmtree(os.path.join('.', 'certificate')) 12 | 13 | def test_generated_files_present(self): 14 | self.assertTrue(os.path.isfile(os.path.join('.', 'certificate', 'ca.crt'))) 15 | self.assertTrue(os.path.isfile(os.path.join('.', 'certificate', 'ca.csr'))) 16 | self.assertTrue(os.path.isfile(os.path.join('.', 'certificate', 'ca.key'))) 17 | self.assertTrue(os.path.isfile(os.path.join('.', 'certificate', 'ca.srl'))) 18 | self.assertTrue(os.path.isfile(os.path.join('.', 'certificate', 'certificate.crt'))) 19 | self.assertTrue(os.path.isfile(os.path.join('.', 'certificate', 'certificate.csr'))) 20 | self.assertTrue(os.path.isfile(os.path.join('.', 'certificate', 'certificate.key'))) 21 | 22 | #Technically not a memory efficient test for md5 checksum, but who cares in a test scenario 23 | #when the file is small? 24 | def test_certificate_regeneration_works(self): 25 | previousSrlHash = hashlib.md5(open(os.path.join('.', 'certificate', 'ca.srl'), 'rb').read()).hexdigest() 26 | subprocess.check_call("docker-compose up certificate-generator", shell=True, cwd=os.path.join('.', 'certificate')) 27 | currentSrlHash = hashlib.md5(open(os.path.join('.', 'certificate', 'ca.srl'), 'rb').read()).hexdigest() 28 | self.assertNotEqual(previousSrlHash, currentSrlHash) 29 | 30 | def test_certificate_is_valid(self): 31 | output = subprocess.check_output("openssl verify -CAfile ca.crt certificate.crt", shell=True, cwd=os.path.join('.', 'certificate')) 32 | self.assertEqual(output.strip(), "certificate.crt: OK") 33 | 34 | def test_certificate_has_correct_values(self): 35 | output = subprocess.check_output("openssl x509 -in certificate.crt -text -noout", shell=True, cwd=os.path.join('.', 'certificate')) 36 | self.assertIsNotNone(re.search('Issuer: C=CA, ST=Quebec, L=Montreal, O=Any, OU=IT, CN=dev.cadomain.com/emailAddress=email@cadomain.com', output)) 37 | self.assertIsNotNone(re.search('Subject: C=CA, ST=Quebec, L=Montreal, O=Any, OU=IT, CN=dev.mydomain.com/emailAddress=email@mydomain.com', output)) 38 | self.assertIsNotNone(re.search('Public-Key: \(2048 bit\)', output)) 39 | self.assertIsNotNone(re.search('Subject Alternative Name:', output)) 40 | self.assertIsNotNone(re.search('DNS:dev.mydomain.com, DNS:test.mydomain.com', output)) 41 | 42 | if __name__ == '__main__': 43 | unittest.main() 44 | -------------------------------------------------------------------------------- /headless-factorio-server/templates/map-gen-settings.json.j2: -------------------------------------------------------------------------------- 1 | { 2 | "_terrain_segmentation_comment": "Inverse of map scale", 3 | "terrain_segmentation": 1, 4 | 5 | "_water_comment": 6 | [ 7 | "Multiplier for water 'coverage' - higher increases the water level.", 8 | "Water level = 10 * log2(this value)" 9 | ], 10 | "water": {{ water_elevation }}, 11 | 12 | "_comment_width+height": "Width and height of map, in tiles; 0 means infinite", 13 | "width": {{ map_width }}, 14 | "height": {{ map_height }}, 15 | 16 | "_starting_area_comment": "Multiplier for 'biter free zone radius'", 17 | "starting_area": {{ biter_free_starting_area }}, 18 | 19 | "peaceful_mode": {{ peaceful_mode }}, 20 | 21 | "autoplace_controls": 22 | { 23 | "coal": {"frequency": {{ coal['frequency'] }}, "size": {{ coal['size'] }}, "richness": {{ coal['richness'] }}}, 24 | "stone": {"frequency": {{ stone['frequency'] }}, "size": {{ stone['size'] }}, "richness": {{ stone['richness'] }}}, 25 | "copper-ore": {"frequency": {{ copper_ore['frequency'] }}, "size": {{ copper_ore['size'] }}, "richness": {{ copper_ore['richness'] }}}, 26 | "iron-ore": {"frequency": {{ iron_ore['frequency'] }}, "size": {{ iron_ore['size'] }}, "richness": {{ iron_ore['richness'] }}}, 27 | "uranium-ore": {"frequency": {{ uranium_ore['frequency'] }}, "size": {{ uranium_ore['size'] }}, "richness": {{ uranium_ore['richness'] }}}, 28 | "crude-oil": {"frequency": {{ crude_oil['frequency'] }}, "size": {{ crude_oil['size'] }}, "richness": {{ crude_oil['richness'] }}}, 29 | "trees": {"frequency": {{ trees['frequency'] }}, "size": {{ trees['size'] }}, "richness": {{ trees['richness'] }}}, 30 | "enemy-base": {"frequency": {{ enemy_base['frequency'] }}, "size": {{ enemy_base['size'] }}, "richness": {{ enemy_base['richness'] }}} 31 | }, 32 | 33 | "cliff_settings": 34 | { 35 | "_name_comment": "Name of the cliff prototype", 36 | "name": "cliff", 37 | 38 | "_cliff_elevation_0_comment": "Elevation of first row of cliffs", 39 | "cliff_elevation_0": 10, 40 | 41 | "_cliff_elevation_interval_comment": "Elevation difference between successive rows of cliffs", 42 | "cliff_elevation_interval": 10, 43 | 44 | "_richness_comment": "Multiplier for cliff continuity; 0 will result in no cliffs, 10 will make all cliff rows completely solid", 45 | "richness": 1 46 | }, 47 | 48 | "_property_expression_names_comment": 49 | [ 50 | "Overrides for property value generators", 51 | "Elevation influences water and cliff placement.", 52 | "Leave it blank to get 'normal' terrain.", 53 | "Use '0_16-elevation' to reproduce terrain from 0.16.", 54 | "Use '0_17-island' to get an island." 55 | ], 56 | "property_expression_names": 57 | { 58 | "elevation": "0_17-island", 59 | 60 | "control-setting:aux:bias": "0.300000", 61 | "control-setting:aux:frequency:multiplier": "1.333333", 62 | "control-setting:moisture:bias": "0.100000", 63 | "control-setting:moisture:frequency:multiplier": "0.500000" 64 | }, 65 | 66 | "starting_points": 67 | [ 68 | {"x": 1000, "y": 2000} 69 | ], 70 | 71 | "_seed_comment": "Use null for a random seed, number for a specific seed.", 72 | "seed": {{ seed }} 73 | } 74 | -------------------------------------------------------------------------------- /node-app/image-builder/README.md: -------------------------------------------------------------------------------- 1 | ##Automated Image Creation Using the image-builder Image and Customized docker-compose.yml File Derived From the Template 2 | 3 | Take the docker-compose.yml template file and customize is for your needs (any parts between <<...>> should be customised). 4 | 5 | ###Build Note 6 | 7 | Because the docker client runs in a container and the docker daemon that actually builds the image runs on the local machine outside the container the client runs on, I had to do a work-around to make the app files available to the daemon. 8 | 9 | Basically, the client runs an http file server and passes in the dockerfile wget commands to the daemon to fetch the files from the server. This means that the build container must map a port to the local machine. 10 | 11 | Furthermore, it implies an additional delay at build time, but it also makes the resulting image more efficient (all files are imported in a single RUN statement resulting in a single layer). 12 | 13 | ###Customizations 14 | 15 | * container-name: Name of the container that builds the image (mostly useful to avoid name clashed with already running containers) 16 | * environment 17 | * UID: Running user ID of the image 18 | * SOURCE_IMAGE: This optional environment variable allows you to use a source image other than the default (magnitus/node-app:4 at the time of this writing). Useful if you want to use the slim version (magnitus/node-app:4-slim), node 6 (magnitus/node-app:6 or magnitus/node-app:6-slim) or an image that adds extra stuff to the default image (extra environment variables, global modules, etc) 19 | * OUTPUT_IMAGE: Full image name of the resulting image 20 | * IGNORE: Regex pattern identifiying files that the dockerfile should not copy (for example, my text editor always creates backup files ending with ~ that I don't want included in a production image) 21 | * EXTERNAL_PORT: Port on your local machine that your container maps to. It's extremely important that this value corresponds to the mapping that you give in the "ports" section. 22 | * DOCKER_LOCALHOST: Address if your localhost machine on the docker networking interface (in Linux, run ifconfig to find it, you should have a 'docker0' interface by default with an 'inet addr' entry) 23 | * CACHE: Whether to use cached intermediate images or not when building anew (should be yes or no) 24 | * NPM_COMMAND: This optional environment variable allows you to specify which npm command is used to launch the app when a container boots from the generated image. Defaults to 'start' (ie, npm run start). 25 | * volume mapping 26 | * App directory: Change the LHS of the volume mapping to map to the directory where your app is contained 27 | * Shared directory: Change the LHS of the volume mapping to map to the directory where your local shared modules are located 28 | * ports: Change the LHS entry to a free port on your host. Don't forget to give the same value to the EXTERNAL_PORT environment variable. 29 | 30 | ###Output 31 | 32 | The corresponding image should have been built by the docker-daemon on your machine. 33 | 34 | ###Examples 35 | 36 | The 'image-builder-image-example' directory contain an example, adapted to have its image automatically generated (port 8080 will need to be free on your machine for the example to work). 37 | -------------------------------------------------------------------------------- /react-build/example/lib/participants.js: -------------------------------------------------------------------------------- 1 | /* 2 | Design notes: Idem what was written in pot for class design 3 | 4 | Also, while it would have been more intuitive to map the participants as a {'name': number, ...} structure, 5 | the {'number': 'name', ...} structure fits the access pattern of the class better. 6 | */ 7 | 8 | function participants(balls) 9 | { 10 | if((!balls) || balls <= 0) 11 | { 12 | throw new Error("participants.constructor:ballsBadValue"); 13 | } 14 | 15 | //Classical pattern to save end-user of the api from having to use the new operator 16 | if(this instanceof participants) 17 | { 18 | this.balls = balls; 19 | this.participants = {}; 20 | this.names = []; //Member to efficiently test new names against existing ones 21 | } 22 | else 23 | { 24 | return new participants(balls); 25 | } 26 | } 27 | 28 | participants.prototype.add = function(name) { 29 | if(Object.keys(this.participants).length == this.balls) 30 | { 31 | throw new Error("participants.add:full"); 32 | } 33 | 34 | if(name === "" || name === undefined || name === null) 35 | { 36 | throw new Error("participants.add:badName"); 37 | } 38 | 39 | if(this.names.some(function(_name) { 40 | return _name == name; 41 | })) 42 | { 43 | throw new Error("participants.add:nameExists"); 44 | } 45 | else 46 | { 47 | this.names.push(name); 48 | } 49 | 50 | /*Map the available values left to a range. 51 | Makes traversal slower when almost no values are taken, but greatly improves performance 52 | when all balls are almost taken (ex: 45 balls out of 50). Performance could be improved further 53 | by keeping track of the mapping and updating it as we insert values. */ 54 | var range = this.balls - Object.keys(this.participants).length; 55 | var result = Math.floor((Math.random() * range) + 1); 56 | 57 | var index = 1; 58 | while(true) 59 | { 60 | if(this.participants[index] === undefined) 61 | { 62 | if(result == 1) 63 | { 64 | this.participants[index] = name; 65 | break; 66 | } 67 | else 68 | { 69 | result--; 70 | } 71 | } 72 | index++; 73 | } 74 | 75 | return index; 76 | } 77 | 78 | participants.prototype.getNames = function() { 79 | return this.names; 80 | } 81 | 82 | participants.prototype.getRanks = function(draws) { 83 | var result = []; 84 | draws.forEach((function(draw) { 85 | var participant = this.participants[draw]; 86 | participant = participant === undefined ? null : participant; 87 | result.push(participant); 88 | }).bind(this)); 89 | return result; 90 | } 91 | 92 | participants.prototype.getWinnings = function(ratios) { 93 | var result = {}; 94 | for(key in ratios) 95 | { 96 | if(this.participants[key] !== undefined) 97 | { 98 | result[this.participants[key]] = ratios[key]; 99 | } 100 | } 101 | 102 | return result; 103 | } 104 | 105 | module.exports = participants; -------------------------------------------------------------------------------- /react-build/example-onbuild/lib/participants.js: -------------------------------------------------------------------------------- 1 | /* 2 | Design notes: Idem what was written in pot for class design 3 | 4 | Also, while it would have been more intuitive to map the participants as a {'name': number, ...} structure, 5 | the {'number': 'name', ...} structure fits the access pattern of the class better. 6 | */ 7 | 8 | function participants(balls) 9 | { 10 | if((!balls) || balls <= 0) 11 | { 12 | throw new Error("participants.constructor:ballsBadValue"); 13 | } 14 | 15 | //Classical pattern to save end-user of the api from having to use the new operator 16 | if(this instanceof participants) 17 | { 18 | this.balls = balls; 19 | this.participants = {}; 20 | this.names = []; //Member to efficiently test new names against existing ones 21 | } 22 | else 23 | { 24 | return new participants(balls); 25 | } 26 | } 27 | 28 | participants.prototype.add = function(name) { 29 | if(Object.keys(this.participants).length == this.balls) 30 | { 31 | throw new Error("participants.add:full"); 32 | } 33 | 34 | if(name === "" || name === undefined || name === null) 35 | { 36 | throw new Error("participants.add:badName"); 37 | } 38 | 39 | if(this.names.some(function(_name) { 40 | return _name == name; 41 | })) 42 | { 43 | throw new Error("participants.add:nameExists"); 44 | } 45 | else 46 | { 47 | this.names.push(name); 48 | } 49 | 50 | /*Map the available values left to a range. 51 | Makes traversal slower when almost no values are taken, but greatly improves performance 52 | when all balls are almost taken (ex: 45 balls out of 50). Performance could be improved further 53 | by keeping track of the mapping and updating it as we insert values. */ 54 | var range = this.balls - Object.keys(this.participants).length; 55 | var result = Math.floor((Math.random() * range) + 1); 56 | 57 | var index = 1; 58 | while(true) 59 | { 60 | if(this.participants[index] === undefined) 61 | { 62 | if(result == 1) 63 | { 64 | this.participants[index] = name; 65 | break; 66 | } 67 | else 68 | { 69 | result--; 70 | } 71 | } 72 | index++; 73 | } 74 | 75 | return index; 76 | } 77 | 78 | participants.prototype.getNames = function() { 79 | return this.names; 80 | } 81 | 82 | participants.prototype.getRanks = function(draws) { 83 | var result = []; 84 | draws.forEach((function(draw) { 85 | var participant = this.participants[draw]; 86 | participant = participant === undefined ? null : participant; 87 | result.push(participant); 88 | }).bind(this)); 89 | return result; 90 | } 91 | 92 | participants.prototype.getWinnings = function(ratios) { 93 | var result = {}; 94 | for(key in ratios) 95 | { 96 | if(this.participants[key] !== undefined) 97 | { 98 | result[this.participants[key]] = ratios[key]; 99 | } 100 | } 101 | 102 | return result; 103 | } 104 | 105 | module.exports = participants; -------------------------------------------------------------------------------- /node-app/base-image/README.md: -------------------------------------------------------------------------------- 1 | ##Manual Dockerfile Creation From Base Image and Customization of 'dockerfile-template' 2 | 3 | Take the dockerfile-template file (or the dockerfile-template-slim file if your prefer more barebone small images) and customize it to your needs. Once that is done, use the modified dockerfile to build your production image. 4 | 5 | ###Customizations 6 | 7 | - UID Environment Variable: Determines the user and group ID that the node app will run under in the container 8 | - NPM_COMMAND Environment Variable: Determines the command that will be passed as to "npm run" when the container launches. Defaults to "start". 9 | - TOOL Environment Variable: Tool that you want to use to install your dependencies, link your shared modules and launch your program. Defaults to "npm". Can be set to "yarn" instead. 10 | - app content: This should contain your node application (location of package.json file and app-specific entrypoint and dependencies) 11 | - shared modules content: 12 | 13 | This should contain any recurring private modules that tend to be used accross apps (or accross containers in the same application if you split it into several containers which is admitedly my primary use-case). 14 | 15 | Those modules can be expressed as a dependency elsewhere by adding their name to the 'localDependencies' entry in the package.json file of the dependent (which is an array of shared module names, as named in their respectif package.json files, see the example). 16 | 17 | Afterwards, they can be required by the dependend by their module name (as defined in their package.json file). 18 | 19 | - npm modules: 20 | 21 | This should contain a semi-colon separated list of npm modules that you want installed and accessible everywhere in your app. 22 | 23 | Note that these "global" npm modules are fallbacks will only be used by your app and shared modules if they are absent from the dependencies in package.json files or if the greater version number matches that of the package.json dependency. 24 | 25 | In the context of application-specific containers with a lot of in-house modules, I think it's a decent compromise between global hell and DRY. 26 | 27 | This allows you to do something like this: say that your app and all shared modules but one use version 3 of bluebird and one shared module use version 2 of bluebird, you can put 'bluebird@3' in the NPM_MODULES environment variable and then put a version 2 dependency in the package.json file of the shared module that uses version 2. 28 | 29 | ###Tag Convention 30 | 31 | The first number appearing in tag names refers to the version of node the image uses. 32 | 33 | The second number appearing in tag names after the 'v' refers to the revision of the image (which increments as improvements are made). 34 | 35 | ###Examples 36 | 37 | The 'example' directory contain an example of a manually generated dockerfile for a project with shared dependencies. 38 | 39 | The 'example2' directory contain an example for a basic 'hello-world' hapi app. 40 | 41 | The 'example3' directory contains a modified version of the 'example' with shared dependencies layered more deedply into the directory structure and one shared dependency requiring another. 42 | 43 | The 'example4' directory contains an example that illustrates the use of the NPM_MODULE environment variable for a global npm module combined with a package.json version override for a shared module. 44 | -------------------------------------------------------------------------------- /react-build/example/app/javascript/app.jsx: -------------------------------------------------------------------------------- 1 | var React = require('react'); 2 | var ReactDOM = require('react-dom'); 3 | 4 | var pot = require('pot'); 5 | var participants = require('participants'); 6 | var draw = require('draw'); 7 | 8 | var Header = require('header'); 9 | var RegisterSection = require('register-section'); 10 | var DrawSection = require('draw-section'); 11 | 12 | module.exports = React.createClass({ 13 | addRegistrant: function(name) { 14 | var hasName = this.participants.getNames().some(function(_name) { 15 | return _name == name; 16 | }); 17 | var number = hasName ? -1 : this.participants.add(name); 18 | var lastRegistrant = { 19 | 'name': name, 20 | 'number': number, 21 | 'visible': true 22 | }; 23 | if(!hasName) 24 | { 25 | this.pot.add(10); 26 | } 27 | this.setState({ 28 | 'lastRegistrant': lastRegistrant, 29 | 'potAmount': this.pot.get() 30 | }); 31 | }, 32 | hideRegistrant: function() { 33 | var lastRegistrant = this.state.lastRegistrant; 34 | lastRegistrant.visible = false; 35 | this.setState({ 36 | 'lastRegistrant': lastRegistrant 37 | }); 38 | }, 39 | initiateDraw: function() { 40 | var drawResult = this.draw(); 41 | var ranks = this.participants.getRanks(drawResult); 42 | var winners = ranks.map((function(name, index) { 43 | if(name === null) 44 | { 45 | return null; 46 | } 47 | else 48 | { 49 | return {'name': name, 'ratio': this.props.winRatios[index]}; 50 | } 51 | }).bind(this)); 52 | winners = this.pot.award(winners); 53 | this.setState({ 54 | 'winners': winners, 55 | 'potAmount': this.pot.get() 56 | }); 57 | }, 58 | clearParticipants: function() { 59 | this.participants = participants(this.props.balls); 60 | this.setState({ 61 | 'lastRegistrant': null, 62 | 'potAmount': this.pot.get(), 63 | 'participants': [], 64 | 'winners': null 65 | }); 66 | }, 67 | getInitialState: function () { 68 | this.pot = pot(this.props.initPot); 69 | this.participants = participants(this.props.balls); 70 | this.draw = function() { 71 | return draw(this.props.balls, this.props.draws); 72 | } 73 | return { 74 | 'lastRegistrant': null, 75 | 'potAmount': this.pot.get(), 76 | 'participants': [], 77 | 'winners': null 78 | }; 79 | }, 80 | render: function () { 81 | return ( 82 |
83 |
84 | 85 | 86 |
87 | ); 88 | } 89 | }); 90 | -------------------------------------------------------------------------------- /react-build/example-onbuild/app/javascript/app.jsx: -------------------------------------------------------------------------------- 1 | var React = require('react'); 2 | var ReactDOM = require('react-dom'); 3 | 4 | var pot = require('pot'); 5 | var participants = require('participants'); 6 | var draw = require('draw'); 7 | 8 | var Header = require('header'); 9 | var RegisterSection = require('register-section'); 10 | var DrawSection = require('draw-section'); 11 | 12 | module.exports = React.createClass({ 13 | addRegistrant: function(name) { 14 | var hasName = this.participants.getNames().some(function(_name) { 15 | return _name == name; 16 | }); 17 | var number = hasName ? -1 : this.participants.add(name); 18 | var lastRegistrant = { 19 | 'name': name, 20 | 'number': number, 21 | 'visible': true 22 | }; 23 | if(!hasName) 24 | { 25 | this.pot.add(10); 26 | } 27 | this.setState({ 28 | 'lastRegistrant': lastRegistrant, 29 | 'potAmount': this.pot.get() 30 | }); 31 | }, 32 | hideRegistrant: function() { 33 | var lastRegistrant = this.state.lastRegistrant; 34 | lastRegistrant.visible = false; 35 | this.setState({ 36 | 'lastRegistrant': lastRegistrant 37 | }); 38 | }, 39 | initiateDraw: function() { 40 | var drawResult = this.draw(); 41 | var ranks = this.participants.getRanks(drawResult); 42 | var winners = ranks.map((function(name, index) { 43 | if(name === null) 44 | { 45 | return null; 46 | } 47 | else 48 | { 49 | return {'name': name, 'ratio': this.props.winRatios[index]}; 50 | } 51 | }).bind(this)); 52 | winners = this.pot.award(winners); 53 | this.setState({ 54 | 'winners': winners, 55 | 'potAmount': this.pot.get() 56 | }); 57 | }, 58 | clearParticipants: function() { 59 | this.participants = participants(this.props.balls); 60 | this.setState({ 61 | 'lastRegistrant': null, 62 | 'potAmount': this.pot.get(), 63 | 'participants': [], 64 | 'winners': null 65 | }); 66 | }, 67 | getInitialState: function () { 68 | this.pot = pot(this.props.initPot); 69 | this.participants = participants(this.props.balls); 70 | this.draw = function() { 71 | return draw(this.props.balls, this.props.draws); 72 | } 73 | return { 74 | 'lastRegistrant': null, 75 | 'potAmount': this.pot.get(), 76 | 'participants': [], 77 | 'winners': null 78 | }; 79 | }, 80 | render: function () { 81 | return ( 82 |
83 |
84 | 85 | 86 |
87 | ); 88 | } 89 | }); 90 | -------------------------------------------------------------------------------- /node-app/README.md: -------------------------------------------------------------------------------- 1 | # node-app 2 | 3 | ## Disclaimer 4 | 5 | While nice, the in-project pathless "modules" feature of this image slowed to a crawl during the building phase for me when concurrently building 10+ service images with 20+ shared local dependencies (live and learn). 6 | 7 | It was a nice experiment and it could probably be perfected to actually work well, but I'll tell the interested reader a hard-learned lesson: 8 | 9 | In this day and age, if you need private modules, just pay ~10$/month to npm for a private registry or otherwise work on setting up your own on-prem registry if you have particular privacy/uptime requirements or a shoestring budget or just a cheap employer (seriously, the effort to setup your own on-prem npm registry if you need it is a better investment). 10 | 11 | ## Purpose 12 | 13 | Collection of images to build custom production node application images. 14 | 15 | ## Images 16 | 17 | The Project has 4 main images. Read the documentation provided in the directory of each image for more details about their usage. 18 | 19 | ### base-image 20 | 21 | Base image to build node applications. It can be used on its own by manually building a production dockerfile from the provided template. 22 | 23 | Tags: 4, latest, 4-slim, 6, 6-slim 24 | 25 | ### base-dev-image 26 | 27 | Development image, meant to be used for code that changes often in a mapped volume outside the image. 28 | 29 | Tags: 4-dev, 6-dev 30 | 31 | ### dockerfile-builder 32 | 33 | Image that automatically builds a production dockerfile of a custom node-app with all dependent files packaged with the dockerfile. 34 | 35 | Tag: dockerfile-builder 36 | 37 | ### image-builder 38 | 39 | Image that automatically builds a production image of a custom node-app. 40 | 41 | Tag: image-builder 42 | 43 | ## Assumptions on app structure 44 | 45 | The images provided here assume that your app is broken down in two components: 46 | 47 | - Main App (required): Main app that contains code specialized for the application. 48 | - Shared modules (optional): Re-usable modules that are not published in a registry (and thus cannot be resolved by npm install), but that may be shared by several apps (or perhaps various parts of your main app if it is split in sub-apps) 49 | 50 | ### package.json requirements 51 | 52 | The shared modules and your main app should all contain a package.json file (and in the case of the shared modules, they should have a valid unique name) 53 | 54 | Also, all parts that use shared modules (your main app or other shared modules) should list the shared modules that they use (by name) in the "localDependencies" entry (see the examples) 55 | 56 | ### Degree of support 57 | 58 | - Base Image: The base image, during image construction, will recursively traverse directories in the shared modules, find all modules (it will stop recursing in directories containing a package.json file and will skip over directories named "node_modules") and resolve depencencies (in the main app and other shared modules) via linking. 59 | - Dockerfile Builder: Currently, the dockerfile builder will create dockerfiles and selectively package all dependencies by looking at the top level directories of the shared modules directory only (it does not traverse sub-directories). I plan to make it recursive soon. 60 | - Image Builder: The image build will only copy shared dependencies used by the app in the image. It will recursively traverse the dependencies to make sure that dependencies of dependencies are properly copied. 61 | -------------------------------------------------------------------------------- /react-build/README.md: -------------------------------------------------------------------------------- 1 | # react-build 2 | 3 | ## Notice 4 | 5 | While functional, the tooling for this image, with browserify, is dated by 2017 standards. Most frontend projects would now use es6 modules with webpack. 6 | 7 | As I'm now in a more backend phase of my workflow, I'll revisit this image when the need for it is felt. 8 | 9 | ## Purpose 10 | 11 | Images to build single-file react bundles with commonjs modules as well as (optional) es-2015, jsx, minification and file watch support. 12 | 13 | Makes use of browserify and babel. 14 | 15 | ## Images 16 | 17 | The are two main images: 18 | 19 | - the onbuild image (onbuild tag) that needs to be the parent of a child image, but that has the final image execute with reduced privilege 20 | - the regular image (latest tag) that can be used directly, but has to run as root 21 | - Additionally, both images have a slim variant that is based on the slim node image 22 | 23 | ## Usage 24 | 25 | ### Environment Variables 26 | 27 | Both the onbuild and regular image need to be executed with the BUILD_FILE environment variable set to the path in the container's file system where the build file can be found. 28 | 29 | Additionally, because the regular image executes as root, it needs an OUTPUT_UID environment variable that sets which user will be the owner of the final bundled file. 30 | 31 | ### Mapped Volumes 32 | 33 | Both images should be executed in a container where all the source code files (js and jsx) to compile, the build file (json) and the distribution directory are mapped between the host filesystem and the container filesystem (see exemples). 34 | 35 | Alternatively, if you have a more strict containers-only build flow, shared docker-managed volumes might also do the work, though such considerations are beyond the scope of this documentation. 36 | 37 | ### dockerfile 38 | 39 | If you use the onbuild image, you need to finalize the image you'll use in a dockerfile. 40 | 41 | You need to perform the following tasks in the dockerfile: 42 | 43 | - Set the UID environment variable to the user ID who should own the files you'll operate on on your host 44 | - Run the finalize.sh script 45 | - Set the container user to UID 46 | 47 | See the onbuild exemple for an implementation of this. 48 | 49 | ### build file 50 | 51 | The build file is a json file that directs how your source files are processed and bundled into the final file. 52 | 53 | Here are the entries: 54 | 55 | - destination: Path of the final bundled file in the container 56 | - dependencies: Array of external dependencies you'll use. Possible values are: react, react-dom, redux. Those external dependencies can be required under those names in your code 57 | - watch: Boolean that sets whether the container should compile your code once or whether it should compile it and re-compile it each time any of the source files are changed 58 | - minify: Boolean that specifies if the result code should be minifed. If set to true, the code will be minified with uglify. 59 | - modules: Object having your module names as keys and the path of their corresponding source file as values. The '*' entry is a special entry. It's an array of folders containing files which should also be bundled and whose module name is their file name, without the extension. 60 | - entrypoints: List of files (or folders containing the files) that should be executed directly when the bundled file is loaded (module code only executes when first required) 61 | - extensions: Array of file extensions that should be included during folder traversals. If this property is not defined, all files will be processed in entries specifying folders, no matter the extension. 62 | -------------------------------------------------------------------------------- /headless-factorio-server/templates/server-settings.json.j2: -------------------------------------------------------------------------------- 1 | { 2 | "name": "{{ game_name }}", 3 | "description": "{{ game_description }}", 4 | "tags": ["game", "tags"], 5 | 6 | "_comment_max_players": "Maximum number of players allowed, admins can join even a full server. 0 means unlimited.", 7 | "max_players": {{ max_players }}, 8 | 9 | "_comment_visibility": ["public: Game will be published on the official Factorio matching server", 10 | "lan: Game will be broadcast on LAN"], 11 | "visibility": 12 | { 13 | "public": false, 14 | "lan": false 15 | }, 16 | 17 | "_comment_credentials": "Your factorio.com login credentials. Required for games with visibility public", 18 | "username": "", 19 | "password": "", 20 | 21 | "_comment_token": "Authentication token. May be used instead of 'password' above.", 22 | "token": "", 23 | 24 | "game_password": "{{ game_password }}", 25 | 26 | "_comment_require_user_verification": "When set to true, the server will only allow clients that have a valid Factorio.com account", 27 | "require_user_verification": false, 28 | 29 | "_comment_max_upload_in_kilobytes_per_second" : "optional, default value is 0. 0 means unlimited.", 30 | "max_upload_in_kilobytes_per_second": 0, 31 | 32 | "_comment_max_upload_slots" : "optional, default value is 5. 0 means unlimited.", 33 | "max_upload_slots": 5, 34 | 35 | "_comment_minimum_latency_in_ticks": "optional one tick is 16ms in default speed, default value is 0. 0 means no minimum.", 36 | "minimum_latency_in_ticks": 0, 37 | 38 | "_comment_ignore_player_limit_for_returning_players": "Players that played on this map already can join even when the max player limit was reached.", 39 | "ignore_player_limit_for_returning_players": false, 40 | 41 | "_comment_allow_commands": "possible values are, true, false and admins-only", 42 | "allow_commands": "admins-only", 43 | 44 | "_comment_autosave_interval": "Autosave interval in minutes", 45 | "autosave_interval": {{ auto_save_interval }}, 46 | 47 | "_comment_autosave_slots": "server autosave slots, it is cycled through when the server autosaves.", 48 | "autosave_slots": {{ auto_save_slots }}, 49 | 50 | "_comment_afk_autokick_interval": "How many minutes until someone is kicked when doing nothing, 0 for never.", 51 | "afk_autokick_interval": 0, 52 | 53 | "_comment_auto_pause": "Whether should the server be paused when no players are present.", 54 | "auto_pause": true, 55 | 56 | "only_admins_can_pause_the_game": true, 57 | 58 | "_comment_autosave_only_on_server": "Whether autosaves should be saved only on server or also on all connected clients. Default is true.", 59 | "autosave_only_on_server": true, 60 | 61 | "_comment_non_blocking_saving": "Highly experimental feature, enable only at your own risk of losing your saves. On UNIX systems, server will fork itself to create an autosave. Autosaving on connected Windows clients will be disabled regardless of autosave_only_on_server option.", 62 | "non_blocking_saving": false, 63 | 64 | "_comment_segment_sizes": "Long network messages are split into segments that are sent over multiple ticks. Their size depends on the number of peers currently connected. Increasing the segment size will increase upload bandwidth requirement for the server and download bandwidth requirement for clients. This setting only affects server outbound messages. Changing these settings can have a negative impact on connection stability for some clients.", 65 | "minimum_segment_size": 25, 66 | "minimum_segment_size_peer_count": 20, 67 | "maximum_segment_size": 100, 68 | "maximum_segment_size_peer_count": 10 69 | } 70 | -------------------------------------------------------------------------------- /react-build/code/app/index.js: -------------------------------------------------------------------------------- 1 | const browserify = require('browserify'); 2 | const babelify = require('babelify'); 3 | const watchify = require('watchify'); 4 | const uglifyify = require('uglifyify'); 5 | const fs = require('fs'); 6 | const path = require('path'); 7 | 8 | var es2015 = require('babel-preset-es2015'); 9 | var jsx = require('babel-preset-react'); 10 | 11 | const settings = JSON.parse(fs.readFileSync(process.env.BUILD_FILE, 'utf8')); 12 | 13 | var b = browserify().transform(babelify, {presets: [es2015, jsx]}); 14 | 15 | if(settings.watch) 16 | { 17 | b.plugin(watchify); 18 | } 19 | 20 | if(settings.minify) 21 | { 22 | b.transform(uglifyify); 23 | } 24 | 25 | function recursivelyAddModules(_path) 26 | { 27 | if(fs.lstatSync(_path).isDirectory()) 28 | { 29 | var files = fs.readdirSync(_path); 30 | files.forEach((file) => { 31 | recursivelyAddModules(path.join(_path, file)); 32 | }); 33 | } 34 | else 35 | { 36 | if((!settings.extensions) || settings.extensions.some((extention) => {return ('.'+extention) == path.extname(_path);})) 37 | { 38 | b.require(_path, {'expose': path.basename(_path, path.extname(_path))}); 39 | } 40 | } 41 | } 42 | 43 | function recursivelyAddEntrypoints(_path) 44 | { 45 | if(fs.lstatSync(_path).isDirectory()) 46 | { 47 | var files = fs.readdirSync(_path); 48 | files.forEach((file) => { 49 | recursivelyAddEntrypoints(path.join(_path, file)); 50 | }); 51 | } 52 | else 53 | { 54 | if((!settings.extensions) || settings.extensions.some((extention) => {return ('.'+extention) == path.extname(_path);})) 55 | { 56 | b.add(_path); 57 | } 58 | } 59 | } 60 | 61 | if(settings.modules) 62 | { 63 | Object.keys(settings['modules']).forEach((key) => { 64 | if(key != '*') 65 | { 66 | b.require(settings['modules'][key], {'expose': key}); 67 | } 68 | else 69 | { 70 | settings['modules'][key].forEach((path) => { 71 | recursivelyAddModules(path); 72 | }); 73 | } 74 | }); 75 | } 76 | 77 | if(settings.entrypoints && settings.entrypoints.length) 78 | { 79 | settings.entrypoints.forEach((entrypoint) => { 80 | recursivelyAddEntrypoints(entrypoint); 81 | }); 82 | } 83 | 84 | if(settings.dependencies && settings.dependencies.length) 85 | { 86 | settings.dependencies.forEach((dependency) => { 87 | switch(dependency) 88 | { 89 | case 'react': 90 | b.require(path.join(process.env.APP_DIR, 'node_modules', 'react', 'dist', 'react.min.js'), {'expose': 'react'}); 91 | break; 92 | case 'react-dom': 93 | b.require(path.join(process.env.APP_DIR, 'node_modules', 'react-dom', 'dist', 'react-dom.min.js'), {'expose': 'react-dom'}); 94 | break; 95 | case 'redux': 96 | b.require(path.join(process.env.APP_DIR, 'node_modules', 'redux', 'dist', 'redux.min.js'), {'expose': 'redux'}); 97 | break; 98 | } 99 | }); 100 | } 101 | 102 | function bundle() 103 | { 104 | b.bundle().pipe(fs.createWriteStream(settings.destination)); 105 | if(process.env.OUTPUT_UID) 106 | { 107 | fs.chownSync(settings.destination, Number(process.env.OUTPUT_UID), Number(process.env.OUTPUT_UID)); 108 | } 109 | } 110 | 111 | if(settings.watch) 112 | { 113 | b.on('update', bundle); 114 | } 115 | 116 | bundle(); 117 | 118 | 119 | 120 | -------------------------------------------------------------------------------- /react-build/example/lib/pot.js: -------------------------------------------------------------------------------- 1 | /* 2 | Design note 1: 3 | I first thought about implementing the whole pot state directly inside the module... 4 | ie: var pot = 0; ; module.exports = {'add': add, 'award': award}; 5 | But then, it occured to me that the module would be more extensible if the pot was not a singleton., 6 | 7 | Design note 2: 8 | At first, I though about returning all the methods in the constructor with the pot amount as a shared closure. 9 | In the interest of a slight increase in memory efficiency, I opted for making them prototype properties instead and manipulate the object state. 10 | */ 11 | 12 | function properRatio(ratio) 13 | { 14 | return ratio >= 0 && ratio <= 1.0; 15 | } 16 | 17 | function pot(startingAmount) 18 | { 19 | if(startingAmount < 0) 20 | { 21 | throw new Error("pot.constructor:startingAmountNegative"); 22 | } 23 | 24 | //Classical pattern to save end-user of the api from having to use the new operator 25 | if(this instanceof pot) 26 | { 27 | this.amount = startingAmount; 28 | } 29 | else 30 | { 31 | return new pot(startingAmount); 32 | } 33 | } 34 | 35 | pot.prototype.add = function(amount) { 36 | if(amount < 0) 37 | { 38 | throw new Error("pot.add:amountNegative"); 39 | } 40 | 41 | this.amount += amount; 42 | }; 43 | 44 | pot.prototype.award = function(ratios) { 45 | //temporarily copy amount locality to easily void the entire operation if argument is bad and exception is thrown 46 | var amount = this.amount; 47 | 48 | if(typeof(ratios) == typeof({}) && ratios !== null) //mapping of users with ratios 49 | { 50 | //Variable to verify that the sum of passed ratios is <= 1.0 51 | var ratioSum = 0; 52 | 53 | if(Array.isArray(ratios)) 54 | { //Array of ordered {'name: .., 'ratio': ..} objects 55 | var result = ratios.map((function(user, index) { 56 | if(user !== null) 57 | { 58 | ratioSum += user['ratio']; 59 | var userAward = Math.floor(user['ratio'] * this.amount); //I use this.amount because each ratio is against the full amount, not the remainders :P 60 | amount -= userAward; 61 | return {'name': user['name'], 'award': userAward}; 62 | } 63 | else 64 | { 65 | return null; 66 | } 67 | }).bind(this)); 68 | } 69 | else 70 | { //object of unordered user:ratio mappings 71 | var result = {}; 72 | 73 | for(user in ratios) 74 | { 75 | if(!properRatio(ratios[user])) 76 | { 77 | throw new Error("pot.award:ratioOutOfBound"); 78 | } 79 | 80 | ratioSum += ratios[user]; 81 | result[user] = Math.floor(ratios[user] * this.amount); //I use this.amount because each ratio is against the full amount, not the remainders :P 82 | amount -= result[user]; 83 | } 84 | } 85 | 86 | if(ratioSum > 1.0) 87 | { 88 | throw new Error("pot.award:ratiosSumGreaterThan1"); 89 | } 90 | 91 | this.amount = amount; //Everything is ok, now we can permanently finalize the operation 92 | 93 | return result; 94 | } 95 | 96 | throw new Error("pot.award:ratiosNotObjectOrNull"); 97 | }; 98 | 99 | pot.prototype.get = function() { 100 | return this.amount; 101 | }; 102 | 103 | module.exports = pot; -------------------------------------------------------------------------------- /react-build/example-onbuild/lib/pot.js: -------------------------------------------------------------------------------- 1 | /* 2 | Design note 1: 3 | I first thought about implementing the whole pot state directly inside the module... 4 | ie: var pot = 0; ; module.exports = {'add': add, 'award': award}; 5 | But then, it occured to me that the module would be more extensible if the pot was not a singleton., 6 | 7 | Design note 2: 8 | At first, I though about returning all the methods in the constructor with the pot amount as a shared closure. 9 | In the interest of a slight increase in memory efficiency, I opted for making them prototype properties instead and manipulate the object state. 10 | */ 11 | 12 | function properRatio(ratio) 13 | { 14 | return ratio >= 0 && ratio <= 1.0; 15 | } 16 | 17 | function pot(startingAmount) 18 | { 19 | if(startingAmount < 0) 20 | { 21 | throw new Error("pot.constructor:startingAmountNegative"); 22 | } 23 | 24 | //Classical pattern to save end-user of the api from having to use the new operator 25 | if(this instanceof pot) 26 | { 27 | this.amount = startingAmount; 28 | } 29 | else 30 | { 31 | return new pot(startingAmount); 32 | } 33 | } 34 | 35 | pot.prototype.add = function(amount) { 36 | if(amount < 0) 37 | { 38 | throw new Error("pot.add:amountNegative"); 39 | } 40 | 41 | this.amount += amount; 42 | }; 43 | 44 | pot.prototype.award = function(ratios) { 45 | //temporarily copy amount locality to easily void the entire operation if argument is bad and exception is thrown 46 | var amount = this.amount; 47 | 48 | if(typeof(ratios) == typeof({}) && ratios !== null) //mapping of users with ratios 49 | { 50 | //Variable to verify that the sum of passed ratios is <= 1.0 51 | var ratioSum = 0; 52 | 53 | if(Array.isArray(ratios)) 54 | { //Array of ordered {'name: .., 'ratio': ..} objects 55 | var result = ratios.map((function(user, index) { 56 | if(user !== null) 57 | { 58 | ratioSum += user['ratio']; 59 | var userAward = Math.floor(user['ratio'] * this.amount); //I use this.amount because each ratio is against the full amount, not the remainders :P 60 | amount -= userAward; 61 | return {'name': user['name'], 'award': userAward}; 62 | } 63 | else 64 | { 65 | return null; 66 | } 67 | }).bind(this)); 68 | } 69 | else 70 | { //object of unordered user:ratio mappings 71 | var result = {}; 72 | 73 | for(user in ratios) 74 | { 75 | if(!properRatio(ratios[user])) 76 | { 77 | throw new Error("pot.award:ratioOutOfBound"); 78 | } 79 | 80 | ratioSum += ratios[user]; 81 | result[user] = Math.floor(ratios[user] * this.amount); //I use this.amount because each ratio is against the full amount, not the remainders :P 82 | amount -= result[user]; 83 | } 84 | } 85 | 86 | if(ratioSum > 1.0) 87 | { 88 | throw new Error("pot.award:ratiosSumGreaterThan1"); 89 | } 90 | 91 | this.amount = amount; //Everything is ok, now we can permanently finalize the operation 92 | 93 | return result; 94 | } 95 | 96 | throw new Error("pot.award:ratiosNotObjectOrNull"); 97 | }; 98 | 99 | pot.prototype.get = function() { 100 | return this.amount; 101 | }; 102 | 103 | module.exports = pot; -------------------------------------------------------------------------------- /headless-factorio-server/README.md: -------------------------------------------------------------------------------- 1 | # Overview 2 | 3 | This image facilitates the operation of a headless Factorio server by wrapping the headless server factorio binary with some python scripts. 4 | 5 | Given that the binary is not MIT, I won't publish the image on Docker Hub, but you can build it yourself from the Dockerfile here. 6 | 7 | # Running Demo Environment 8 | 9 | To run the server on your local machine, follow the steps below. 10 | 11 | 1. Edit the docker-compose file to change the whitelist adminlist and any other settings you want to change (see environment variables below) 12 | 2. Make sure you have docker and docker-compose installed 13 | 3. Run: **docker-compose up -d** 14 | 4. Open Factorio, click on: Play > Multiplayer > Connect to a Server (enter 127.0.0.1:8080 in the box) 15 | 16 | # Environment Variables 17 | 18 | The behavior of the server is customizable with the following environment variables: 19 | 20 | - GAME_NAME: Name to give your game 21 | - GAME_DESCRIPTION: Description to give your game 22 | - GAME_PASSWORD: Password users will need to supply to join your game 23 | - MAX_PLAYERS: Integer specifying the max number of players who can join. Defaults to unlimited 24 | - AUTO_SAVE_INTERVAL: Interval of time in minutes between automated saves (defaults to 10) 25 | - AUTO_SAVE_SLOTS: Number of save slots that are kept (defaults to 5) 26 | - POLLUTION_ENABLED: Whether pollution exists in the game. Game be 'true' or 'false'. Defaults to 'true'. 27 | - EVOLUTION_ENABLED: Whether enemies evolve. Game be 'true' or 'false'. Defaults to 'true'. 28 | - EXPANSION_ENABLED: Whether enemies build new bases. Game be 'true' or 'false'. Defaults to 'true'. 29 | - MIN_EXPANSION_COOLDOWN: Minimum period of time in minutes before enemies try to build a new base. Defaults to 4. 30 | - MAX_EXPANSION_COOLDOWN: Maximum period of time in minutes before enemies try to build a new base. Defaults to 60. 31 | - MIN_SETTLER_GROUP_SIZE: Minimum size of the group enemies send to build a new base. Defaults to 5. 32 | - MAX_SETTLER_GROUP_SIZE: Maximum size of the group enemies send to build a new base. Defaults to 20. 33 | - TECHNOLOGY_PRICE_MULTIPLIER: Cost multiplier on normal costs to research technologies as an integer. Defaults to 1. 34 | - EVOLUTION_TIME_FACTOR: How much enemies evolve over time as a real number. Defaults to 0.000004. 35 | - EVOLUTION_DESTROY_FACTOR: How much enemies evolve when you destroy their buildings as a real number. Defaults to 0.002. 36 | - EVOLUTION_POLLUTION_FACTOR: How enemies evolve given the amount of pollution you generate as a real number. Defaults to 0.0000009. 37 | - SEED: Provide a seed to generate a game identical to a past game you generated. Defaults to null for a random game. 38 | - MAP_WIDTH: Width of the map in tiles. Defaults to 0 for maximum (a very large map) 39 | - MAP_HEIGHT: Height of the map in tiles. Defaults to 0 for maximum (a very large map) 40 | - BITER_FREE_STARTING_AREA: Multiplier of the normal enemy free radius in the early game as an integer. Defaults to 1. 41 | - WATER_ELEVATION: Multiplier on the normal water levels (to have more water, less land), with a log applied to it before multiplying. Defaults to 1. 42 | - PEACEFUL_MODE: Whether you have enemies or not as 'true' or 'false'. Defaults to 'false' (ie, you have enemies) 43 | - ADMIN_PLAYERS: Comma separated list of players that you want to be admin. If missing, the will be no admin. 44 | - WHITELISTED_PLAYERS: Comma separated list of players to allow. If missing, anyone who can supply the game's password is allowed. 45 | 46 | There are also various environment variables to set the amount (frequency, size, richness) of various starting resources, but I'm getting lazy. Please, look at the configs.py code file for their names. 47 | 48 | Note that the headless server binary supplied by the makers of Factorio is highly configurable. This is just a subset of possible configurations that I found interesting to play with. 49 | 50 | # Requisite volumes 51 | 52 | You should mount a bind a volume on your machine to the following path in the container to persist data: /opt/data 53 | 54 | # Caveats 55 | 56 | Currently, only non-public mode with no centralized account and no LAN broadcast is supported because that was my use-case which I could troubleshoot. 57 | 58 | Also, I could not make it work inside a docker network with port fowarding so right now, it only works if you run the container on the host network. --------------------------------------------------------------------------------