bunch of stuff in initial commit
This commit is contained in:
Executable
+124
@@ -0,0 +1,124 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Busnet Ansible
|
||||
# @author Craig McDaniel
|
||||
#
|
||||
# This script uses Ansible to provision computers in the BusNet.
|
||||
#
|
||||
|
||||
INCLUDE_DIR="/opt/busnet/git/devops/orchestrate/lib"
|
||||
|
||||
# Read in libs
|
||||
source ${INCLUDE_DIR}/lib.sh
|
||||
|
||||
COMMAND=$1
|
||||
|
||||
# Show help text
|
||||
show_help()
|
||||
{
|
||||
echo
|
||||
echo "BusNet ansible script."
|
||||
echo
|
||||
echo "Usage: $0 <command>"
|
||||
echo
|
||||
echo "General Ansible stuff:"
|
||||
echo "---------------------------------------------------------------------------------------------------------------"
|
||||
echo " --build Build the Anisble docker image. We use this everywhere."
|
||||
echo " --run Start bash shell inside the ansible container."
|
||||
echo " --bootstrap-server Bootstrap a brand new server for the first time. This executes the Ansible bootstrap"
|
||||
echo " role on it. Run this once."
|
||||
echo
|
||||
echo "scanner.busnet:"
|
||||
echo "---------------------------------------------------------------------------------------------------------------"
|
||||
echo " --scanner-direwolf Install and configure direwolf on scanner.busnet"
|
||||
echo
|
||||
}
|
||||
|
||||
|
||||
# Main entry point.
|
||||
main()
|
||||
{
|
||||
# Account/billing server
|
||||
if [ "${COMMAND}" = "--run" ]; then
|
||||
docker_run_it 'ansible-busnet:latest' runner bash
|
||||
|
||||
elif [ "${COMMAND}" = "--bootstrap-server" ]; then
|
||||
ansible_bootstrap_server
|
||||
|
||||
elif [ "${COMMAND}" = "--build" ]; then
|
||||
ansible_build
|
||||
|
||||
elif [ "${COMMAND}" = "--scanner-direwolf" ]; then
|
||||
scanner_direwolf
|
||||
|
||||
# Show Help
|
||||
else
|
||||
show_help
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
ansible_bootstrap_server()
|
||||
{
|
||||
# Check if the private key exists before proceeding.
|
||||
local PRIVATE_KEY_PATH="${HOME}/.ssh/${CONFIG_ANSIBLE_KEY_NAME}"
|
||||
local PUBLIC_KEY_PATH="${PRIVATE_KEY_PATH}.pub"
|
||||
|
||||
if [[ ! -f "$PUBLIC_KEY_PATH" ]]; then
|
||||
echo "Error: Public key not found at $PUBLIC_KEY_PATH"
|
||||
echo "The function generate_busnet_key() should have generated one already. Something did not work correctly. Doing nothing."
|
||||
return 1 # Exit the function with an error code
|
||||
fi
|
||||
|
||||
echo "Bootstrap a new server!"
|
||||
echo "This will copy the SSH key and execute the ansible bootstrap role."
|
||||
echo
|
||||
echo "The hostname you enter below MUST be added to Ansible inventory first. If it's not, go add it now!"
|
||||
echo
|
||||
|
||||
# Prompt for the hostname and the user to connect as.
|
||||
read -e -p "Enter the hostname of the server: " HOSTNAME
|
||||
read -e -p "Enter the remote username (e.g., ec2-user): " USERNAME
|
||||
echo
|
||||
|
||||
# Copy the SSH public key to the remote server.
|
||||
echo "Attempting to copy SSH key to ${USERNAME}@${HOSTNAME}..."
|
||||
if ssh-copy-id -i "${PRIVATE_KEY_PATH}" "${USERNAME}"@"${HOSTNAME}"; then
|
||||
echo "SSH key copied successfully."
|
||||
else
|
||||
echo "Error: Failed to copy SSH key. Please check the hostname, username, and your SSH connection."
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "Running the Ansible playbook..."
|
||||
ansible_playbook playbooks/general/bootstrap.yml "hostname=${HOSTNAME}"
|
||||
if [ $? != 0 ]; then
|
||||
echo
|
||||
echo "Ansible playbook execution failed."
|
||||
echo
|
||||
else
|
||||
echo
|
||||
echo "Ansible playbook execution complete."
|
||||
echo
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
scanner_direwolf()
|
||||
{
|
||||
ansible_playbook playbooks/scanner/direwolf.yml
|
||||
if [ $? != 0 ]; then
|
||||
echo
|
||||
echo "Ansible playbook execution failed."
|
||||
echo
|
||||
else
|
||||
echo
|
||||
echo "Ansible playbook execution complete."
|
||||
echo
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
# Start the script
|
||||
main
|
||||
@@ -0,0 +1,137 @@
|
||||
# Docker compose for our backend system (REST API/Websocket/LDAP)
|
||||
# @author Craig McDaniel
|
||||
#
|
||||
# This runs a backend server in your development environment. This gets you a running API server.
|
||||
# You get:
|
||||
#
|
||||
# * BorgDrone PublicAPI application. This is the web server for the REST API and RealTimeAPI.
|
||||
# - REST API: API endpoint, CB endpoint and SystemAPI endpoint.
|
||||
# - RealTime API: A Websocket server for receiving events in real time.
|
||||
#
|
||||
# * BorgDrone LDAP server application.
|
||||
#
|
||||
# * Local redis cache.
|
||||
#
|
||||
# * Multiple PHP-FPM daemons, each running in their own docker container and on separate TCP ports
|
||||
# so that we can serve up PHP code that need different PHP versions.
|
||||
#
|
||||
|
||||
version: "3.5"
|
||||
|
||||
services:
|
||||
# BorgDrone acts as a web server
|
||||
borgdrone:
|
||||
image: ${APISERVER_IMAGE_NAME}
|
||||
hostname: bg-${HOSTNAME}
|
||||
container_name: borgdrone
|
||||
# Run nodemon for BorgDrone hot reload. Console displays all logs to stdout.
|
||||
command: "node_modules/.bin/nodemon -i node_modules --signal SIGTERM borgdrone.js --console"
|
||||
#command: "/opt/omilia/borgdrone/node_modules/.bin/forever --minUptime 1000 --spinSleepTime 1000 --workingDir /opt/omilia/borgdrone borgdrone.js --console"
|
||||
working_dir: "/opt/omilia/borgdrone"
|
||||
# This starts a mini init program that properly conveys SIGTERM to node when stopping the container.
|
||||
init: true
|
||||
stop_signal: SIGTERM
|
||||
environment:
|
||||
- RELEASE_MODE=dev
|
||||
# Borgdrone needs to know what the host IP address is. It will look for this var.
|
||||
- IP_ADDRESS=${IPADDRESS_API}
|
||||
volumes:
|
||||
- /opt/omilia/svn:/opt/omilia/svn
|
||||
- /opt/omilia/git:/opt/omilia/git
|
||||
# Core and PublicAPI must share the same directory here
|
||||
- /opt/omilia/core:/opt/omilia/core
|
||||
# Map core source tree to current
|
||||
- ${SVN_DIR}/core/src:/opt/omilia/core/${SVN_CODE_NAME}/current
|
||||
- ${SVN_DIR}/lib/ttcore:/opt/omilia/core/${SVN_CODE_NAME}/current/ttcore
|
||||
# Borgdrone source tree map
|
||||
- ${SVN_DIR}/borgdrone/src:/opt/omilia/borgdrone
|
||||
# PublicAPI will move CORE versions into the local storage sometimes
|
||||
- php-core-store:/opt/omilia/mnt/php-core-store
|
||||
# Shared App Data
|
||||
- shared-app-data:/opt/omilia/mnt/shared-app-data
|
||||
restart: on-failure
|
||||
network_mode: "host"
|
||||
|
||||
# Redis short term (local) memory cache.
|
||||
shorttermcache:
|
||||
image: redis:6
|
||||
hostname: shorttermcache
|
||||
container_name: shorttermcache
|
||||
command: "redis-server"
|
||||
restart: on-failure
|
||||
network_mode: "host"
|
||||
|
||||
# PHP-FPM 7.3 listens on port 9000
|
||||
php-fpm-7.3:
|
||||
# See lib/build-php.sh to see where this variable comes from.
|
||||
image: ${PHP_FPM_IMAGE_73}
|
||||
hostname: php-fpm-73
|
||||
container_name: php-fpm-73
|
||||
# Run PHP-FPM and tell it to use the dev config.
|
||||
command: "php-fpm -e --nodaemonize --fpm-config /usr/local/etc/php-fpm.dev.conf"
|
||||
#command: "php-fpm --nodaemonize --fpm-config /usr/local/etc/php-fpm.prod.conf"
|
||||
working_dir: "/opt/omilia"
|
||||
environment:
|
||||
- COOKIE_DOMAIN=omilia.io
|
||||
volumes:
|
||||
# Core and PublicAPI must share the same directory here
|
||||
- /opt/omilia/core:/opt/omilia/core
|
||||
# Map core source tree to current
|
||||
- /opt/omilia/svn:/opt/omilia/svn
|
||||
- ${SVN_DIR}/core/src:/opt/omilia/core/${SVN_CODE_NAME}/current
|
||||
- ${SVN_DIR}/lib/ttcore:/opt/omilia/core/${SVN_CODE_NAME}/current/ttcore
|
||||
# PublicAPI will move CORE versions into the local storage sometimes
|
||||
- php-core-store:/opt/omilia/mnt/php-core-store
|
||||
# Shared App Data
|
||||
- shared-app-data:/opt/omilia/mnt/shared-app-data
|
||||
# Account audio files uploaded or recorded by customers
|
||||
- account-audio-files:/opt/omilia/mnt/account-audio-files
|
||||
restart: on-failure
|
||||
network_mode: "host"
|
||||
|
||||
# PHP-FPM 7.4 listens on port 9001
|
||||
php-fpm-7.4:
|
||||
# See lib/build-php.sh to see where this variable comes from.
|
||||
image: ${PHP_FPM_IMAGE_74}
|
||||
hostname: php-fpm-74
|
||||
container_name: php-fpm-74
|
||||
# Run PHP-FPM and tell it to use the dev config.
|
||||
command: "php-fpm -e --nodaemonize --fpm-config /usr/local/etc/php-fpm.dev.conf"
|
||||
#command: "php-fpm --nodaemonize --fpm-config /usr/local/etc/php-fpm.prod.conf"
|
||||
working_dir: "/opt/omilia"
|
||||
environment:
|
||||
- COOKIE_DOMAIN=omilia.io
|
||||
volumes:
|
||||
# Core and PublicAPI must share the same directory here
|
||||
- /opt/omilia/core:/opt/omilia/core
|
||||
# Map core source tree to current
|
||||
- /opt/omilia/svn:/opt/omilia/svn
|
||||
- ${SVN_DIR}/core/src:/opt/omilia/core/${SVN_CODE_NAME}/current
|
||||
- ${SVN_DIR}/lib/ttcore:/opt/omilia/core/${SVN_CODE_NAME}/current/ttcore
|
||||
# PublicAPI will move CORE versions into the local storage sometimes
|
||||
- php-core-store:/opt/omilia/mnt/php-core-store
|
||||
# Shared App Data
|
||||
- shared-app-data:/opt/omilia/mnt/shared-app-data
|
||||
# Account audio files uploaded or recorded by customers
|
||||
- account-audio-files:/opt/omilia/mnt/account-audio-files
|
||||
restart: on-failure
|
||||
network_mode: "host"
|
||||
|
||||
# Volumes, NFS shares
|
||||
volumes:
|
||||
data:
|
||||
php-core-store:
|
||||
driver_opts:
|
||||
type: nfs
|
||||
o: "addr=fs-007e461671b517080.efs.us-east-1.amazonaws.com,nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,noresvport"
|
||||
device: ":/"
|
||||
shared-app-data:
|
||||
driver_opts:
|
||||
type: nfs
|
||||
o: "addr=fs-09e63d68dea814115.efs.us-east-1.amazonaws.com,nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,noresvport"
|
||||
device: ":/"
|
||||
account-audio-files:
|
||||
driver_opts:
|
||||
type: nfs
|
||||
o: "addr=fs-09d0eb0a28f3cb6b3.efs.us-east-1.amazonaws.com,nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,noresvport"
|
||||
device: ":/account-audio"
|
||||
@@ -0,0 +1,54 @@
|
||||
|
||||
#
|
||||
#version: "3.5"
|
||||
|
||||
services:
|
||||
apache2:
|
||||
image: ${BILLING_APACHE2_IMAGE_NAME}
|
||||
hostname: billing-apache2
|
||||
container_name: billing-apache2
|
||||
restart: on-failure
|
||||
networks:
|
||||
billingnet:
|
||||
ipv4_address: 10.77.93.10
|
||||
volumes:
|
||||
- /opt/neutopia/git/whmcsphp/src:/opt/neutopia/whmcs
|
||||
- ssl-certs:/opt/neutopia/mnt/ssl-certs
|
||||
|
||||
billing-phpfpm:
|
||||
image: ${BILLING_PHPFPM_IMAGE_NAME}
|
||||
hostname: billing-phpfpm
|
||||
container_name: billing-phpfpm
|
||||
# Run PHP-FPM and tell it to use the dev config.
|
||||
#command: "php-fpm -e --nodaemonize --fpm-config /usr/local/etc/php-fpm.dev.conf"
|
||||
#working_dir: "/opt/omilia"
|
||||
#environment:
|
||||
# - COOKIE_DOMAIN=omilia.io
|
||||
networks:
|
||||
billingnet:
|
||||
ipv4_address: 10.77.93.11
|
||||
ipv6_address: 10:77:93::11
|
||||
volumes:
|
||||
- /opt/neutopia/git/whmcsphp/src:/opt/neutopia/whmcs
|
||||
- ssl-certs:/opt/neutopia/mnt/ssl-certs
|
||||
|
||||
|
||||
# These NFS shares require an existing Wireguard VPN to be set up and running on your computer or
|
||||
# on your network.
|
||||
volumes:
|
||||
ssl-certs:
|
||||
driver_opts:
|
||||
type: nfs
|
||||
o: "addr=${ACCOUNT_NFS_SERVER},nfsvers=4.2,rw,hard,timeo=600"
|
||||
device: ":/opt/neutopia/mnt/ssl-certs"
|
||||
|
||||
# Create a network called "billingnet"
|
||||
networks:
|
||||
billingnet:
|
||||
driver: bridge
|
||||
name: "billingnet"
|
||||
enable_ipv6: true
|
||||
ipam:
|
||||
config:
|
||||
- subnet: 10.77.93.0/24
|
||||
- subnet: 10:77:93::/64
|
||||
@@ -0,0 +1,26 @@
|
||||
# Configuration variables
|
||||
|
||||
# By default, platform. Override this when you want to build for another platform.
|
||||
CONFIG_DOCKER_BUILD_PLATFORM="linux/amd64,linux/arm64"
|
||||
|
||||
# These are SSH keys used by Ansible to connect to hosts on BusNet. This key pair will be auto
|
||||
# generated.
|
||||
CONFIG_ANSIBLE_KEY_NAME="ansiblebusnet"
|
||||
|
||||
# This is the location of the ssh keys on your computer.
|
||||
CONFIG_ANSIBLE_KEY_DIR="${HOME}/.ssh"
|
||||
|
||||
# This is where we mount the ssh key dir inside of a container.
|
||||
CONFIG_ANSIBLE_KEY_DIR_INSIDE="/opt/busnet/ssh-keys"
|
||||
|
||||
# Mount these volumes on all containers we run
|
||||
CONFIG_DOCKER_MOUNTS="--mount src="/opt/busnet/git,target=/opt/busnet/git,type=bind"
|
||||
--mount src="/opt/busnet/data,target=/opt/busnet/data,type=bind"
|
||||
--mount src="${CONFIG_ANSIBLE_KEY_DIR},target=${CONFIG_ANSIBLE_KEY_DIR_INSIDE},type=bind"
|
||||
-v /var/run/docker.sock:/var/run/docker.sock
|
||||
"
|
||||
|
||||
# Include this environment variables on all containers we run
|
||||
CONFIG_DOCKER_ENV="--env ANSIBLE_DIR=$ANSIBLE_DIR
|
||||
--env REAL_HOSTNAME=$HOSTNAME
|
||||
"
|
||||
@@ -0,0 +1,363 @@
|
||||
#!/bin/bash
|
||||
# General lib for devops scripts
|
||||
# @author Craig McDaniel
|
||||
#
|
||||
|
||||
# Source config data
|
||||
source ${INCLUDE_DIR}/config.sh
|
||||
|
||||
# Save all arguments to the script here.
|
||||
BASH_ARGS=$@
|
||||
|
||||
# Ensure dir exists
|
||||
mkdir -p /opt/busnet/data
|
||||
|
||||
|
||||
# Make sure there is an ssh key pair for the current user. This will be distributed to servers and
|
||||
# used for Ansible SSH connections. It's not fancy at all. This is a simple solution for the BusNet
|
||||
# system.
|
||||
generate_busnet_key()
|
||||
{
|
||||
local KEY_PATH="${HOME}/.ssh/${CONFIG_ANSIBLE_KEY_NAME}"
|
||||
# Only run if the key isn't there.
|
||||
if [[ ! -f "$KEY_PATH" ]]; then
|
||||
echo "No SSH private key detected for ansible-busnet. Generating one. DO NOT REMOVE THIS!"
|
||||
ssh-keygen -t ed25519 -f "${KEY_PATH}" -N "" -C "ansible-busnet@$(hostname)"
|
||||
fi
|
||||
}
|
||||
generate_busnet_key
|
||||
|
||||
|
||||
# Make sure the docker image specified by $1 is built and available for use.
|
||||
buildx_image()
|
||||
{
|
||||
IMAGE_NAME=$1
|
||||
DOCKERFILE=$2
|
||||
DOCKERDIR=$3
|
||||
#DOCKERARGS=""
|
||||
|
||||
# If --no-cache was specified, pass that on and ALSO add --pull to get the latest images.
|
||||
if [[ "${BASH_ARGS}" =~ "--no-cache" ]]; then
|
||||
DOCKERARGS="${DOCKERARGS} --pull --no-cache"
|
||||
# If --pull was specified, pass just that on.
|
||||
elif [[ "${BASH_ARGS}" =~ "--pull" ]]; then
|
||||
DOCKERARGS="${DOCKERARGS} --pull"
|
||||
fi
|
||||
|
||||
echo "Building docker image ${IMAGE_NAME} using ${DOCKERFILE} in directory ${DOCKERDIR}"
|
||||
echo "Docker args: ${DOCKERARGS}"
|
||||
|
||||
# This uses the new docker builder. It can build multi-platform images. The default-load=true
|
||||
# will load the image into the local machine so that docker image ls shows it.
|
||||
docker buildx create --name busnet-builder --driver-opt=default-load=true
|
||||
|
||||
docker buildx build --builder busnet-builder --tag $IMAGE_NAME $DOCKERARGS --platform $CONFIG_DOCKER_BUILD_PLATFORM --file $DOCKERFILE $DOCKERDIR
|
||||
}
|
||||
|
||||
|
||||
# Execute Ansible inside the specified container. In order for this to work, the container image
|
||||
# must have Ansible and required Ansible modules already installed.
|
||||
# $1 playbook to execute
|
||||
# $2 extra vars to pass to Ansible in --extra-vars
|
||||
#
|
||||
# Set the VARIABLE $DOCKER_OPTIONS with any custom options you want, and we'll pass this to the docker
|
||||
# program verbatim.
|
||||
ansible_playbook()
|
||||
{
|
||||
ANSIBLE_IMAGE_NAME="ansible-busnet"
|
||||
PLAYBOOK=$1
|
||||
EXTRA_VARS=$2
|
||||
echo "Running Ansible playbook ${PLAYBOOK} in a container using ansible image ${ANSIBLE_IMAGE_NAME} ..."
|
||||
|
||||
docker inspect $ANSIBLE_IMAGE_NAME &>/dev/null
|
||||
if [ $? != 0 ]; then
|
||||
if [ "${ANSIBLE_IMAGE_NAME}" == "ansible-busnet" ]; then
|
||||
echo "You need to build the ansible docker image first with --ansible-build"
|
||||
exit 1
|
||||
else
|
||||
echo "I just attempted to run the container $ANSIBLE_IMAGE_NAME, but I could not because it doesn't exist on your system."
|
||||
exit 1
|
||||
fi;
|
||||
fi
|
||||
|
||||
# SSH remote user
|
||||
read -e -p "Enter username for remote SSH: " ansible_user
|
||||
|
||||
# SSH key file
|
||||
ansible_ssh_private_key_file=${CONFIG_ANSIBLE_KEY_DIR_INSIDE}/${CONFIG_ANSIBLE_KEY_NAME}
|
||||
|
||||
EXTRA_VARS="${EXTRA_VARS} ansible_user=${ansible_user} ansible_ssh_private_key_file=${ansible_ssh_private_key_file}"
|
||||
|
||||
echo "EXTRA VARS (if any): ${EXTRA_VARS}"
|
||||
echo
|
||||
docker run \
|
||||
--rm \
|
||||
-it \
|
||||
--network host \
|
||||
$CONFIG_DOCKER_ENV \
|
||||
$CONFIG_DOCKER_MOUNTS \
|
||||
--name ansible-busnet-runner \
|
||||
$DOCKER_OPTIONS \
|
||||
$ANSIBLE_IMAGE_NAME \
|
||||
ansible-playbook $PLAYBOOK --extra-vars "${EXTRA_VARS}"
|
||||
}
|
||||
|
||||
|
||||
# Regular 'ole docker run, non-interactively.
|
||||
#
|
||||
# $1 docker image name to run
|
||||
# $2 name of the container
|
||||
# $3 command to run. Defaults to sleep infinity (what's the point in that)
|
||||
# $4 optional workdir
|
||||
#
|
||||
# Set the variable DOCKER_OPTIONS with any custom options you want, and we'll pass this to the docker
|
||||
# program verbatim.
|
||||
#
|
||||
docker_run()
|
||||
{
|
||||
IMAGE_NAME=$1
|
||||
CONTAINER_NAME=$2
|
||||
|
||||
if [[ -z "$3" ]]; then
|
||||
COMMAND="sleep infinity"
|
||||
else
|
||||
COMMAND=$3
|
||||
fi
|
||||
|
||||
if [[ -z "$4" ]]; then
|
||||
WORKDIR=""
|
||||
else
|
||||
WORKDIR="-w ${4}"
|
||||
fi
|
||||
|
||||
docker inspect $IMAGE_NAME &>/dev/null
|
||||
if [ $? != 0 ]; then
|
||||
if [ "${IMAGE_NAME}" == "ansible-builder" ]; then
|
||||
echo "You need to build the ansible docker image first with --ansible-build"
|
||||
exit 1
|
||||
else
|
||||
echo "I just attempted to run the container $IMAGE_NAME, but I could not because it doesn't exist on your system. You may need to build it first with build.sh"
|
||||
exit 1
|
||||
fi;
|
||||
fi
|
||||
|
||||
# Stop it if it's already running.
|
||||
docker_stop $CONTAINER_NAME
|
||||
|
||||
docker run --rm --network host ${WORKDIR} \
|
||||
$CONFIG_DOCKER_MOUNTS \
|
||||
$CONFIG_DOCKER_ENV \
|
||||
--name $CONTAINER_NAME \
|
||||
$DOCKER_OPTIONS \
|
||||
$IMAGE_NAME \
|
||||
$COMMAND
|
||||
}
|
||||
|
||||
|
||||
# Run a container in interactive mode. When you exit, the container exists and is removed automatically.
|
||||
#
|
||||
# $1 docker image name to run
|
||||
# $2 name of the container
|
||||
# $3 command to run. Defaults to sleep infinity (what's the point in that)
|
||||
# $4 optional workdir
|
||||
#
|
||||
# Set the variable DOCKER_OPTIONS with any custom options you want, and we'll pass this to the docker
|
||||
# program verbatim.
|
||||
#
|
||||
docker_run_it()
|
||||
{
|
||||
IMAGE_NAME=$1
|
||||
CONTAINER_NAME=$2
|
||||
if [[ -z "$3" ]]; then
|
||||
COMMAND="sleep infinity"
|
||||
else
|
||||
COMMAND=$3
|
||||
fi
|
||||
|
||||
if [[ -z "$4" ]]; then
|
||||
WORKDIR=""
|
||||
else
|
||||
WORKDIR="-w ${4}"
|
||||
fi
|
||||
|
||||
docker inspect $IMAGE_NAME &>/dev/null
|
||||
if [ $? != 0 ]; then
|
||||
if [ "${IMAGE_NAME}" == "ansible-builder" ]; then
|
||||
echo "You need to build the ansible docker image first with --ansible-build"
|
||||
exit 1
|
||||
else
|
||||
echo "I just attempted to run the container $IMAGE_NAME, but I could not because it doesn't exist on your system. You may need to build it first with build.sh"
|
||||
exit 1
|
||||
fi;
|
||||
fi
|
||||
|
||||
echo "COmmand: ${COMMAND}"
|
||||
|
||||
# Stop it if it's already running.
|
||||
docker_stop $CONTAINER_NAME
|
||||
|
||||
docker run --rm -it --network host ${WORKDIR} \
|
||||
$CONFIG_DOCKER_MOUNTS \
|
||||
$CONFIG_DOCKER_ENV \
|
||||
--name $CONTAINER_NAME \
|
||||
$DOCKER_OPTIONS \
|
||||
$IMAGE_NAME \
|
||||
$COMMAND
|
||||
}
|
||||
|
||||
|
||||
# Same as docker_run_it() but do not check if the image exists. This works only if the image is
|
||||
# publicly available or in a repo that we have access to. Docker will just fetch the image automatically,
|
||||
# whereas docker_run_it() will throw an error if it doesn't exst locally. Ugh.
|
||||
# $1 docker image name to run
|
||||
# $2 name of the container
|
||||
# $3 command to run. Defaults to sleep infinity (what's the point in that)
|
||||
# $4 optional workdir
|
||||
#
|
||||
# Set the variable DOCKER_OPTIONS with any custom options you want, and we'll pass this to the docker
|
||||
# program verbatim.
|
||||
#
|
||||
docker_run_it_nocheck()
|
||||
{
|
||||
IMAGE_NAME=$1
|
||||
CONTAINER_NAME=$2
|
||||
if [[ -z "$3" ]]; then
|
||||
COMMAND="sleep infinity"
|
||||
else
|
||||
COMMAND=$3
|
||||
fi
|
||||
|
||||
if [[ -z "$4" ]]; then
|
||||
WORKDIR=""
|
||||
else
|
||||
WORKDIR="-w ${4}"
|
||||
fi
|
||||
|
||||
# Stop it if it's already running.
|
||||
docker_stop $CONTAINER_NAME
|
||||
|
||||
docker run --rm -it --network host ${WORKDIR} \
|
||||
$CONFIG_DOCKER_MOUNTS \
|
||||
$CONFIG_DOCKER_ENV \
|
||||
--name $CONTAINER_NAME \
|
||||
$DOCKER_OPTIONS \
|
||||
$IMAGE_NAME \
|
||||
$COMMAND
|
||||
}
|
||||
|
||||
|
||||
# Run and detach a container with the command "sleep infinity". We'll then connect to this container
|
||||
# with Ansible and do some tasks on it, then save its state.
|
||||
# $1 docker image name to run
|
||||
# $2 name of the container
|
||||
# $3 command to run. Defaults to sleep infinity
|
||||
#
|
||||
# Set the variable DOCKER_OPTIONS with any custom options you want, and we'll pass this to the docker
|
||||
# program verbatim.
|
||||
#
|
||||
# Set the variable DOCKER_FORCE_NEW=1 to always start a new container each time. The default is to re-use
|
||||
# already running containers.
|
||||
#
|
||||
docker_run_detach()
|
||||
{
|
||||
IMAGE_NAME=$1
|
||||
CONTAINER_NAME=$2
|
||||
if [[ -z "$3" ]]; then
|
||||
COMMAND="sleep infinity"
|
||||
else
|
||||
COMMAND=$3
|
||||
fi
|
||||
|
||||
docker inspect $IMAGE_NAME &>/dev/null
|
||||
if [ $? != 0 ]; then
|
||||
if [ "${IMAGE_NAME}" == "ansible-builder" ]; then
|
||||
echo "You need to build the ansible docker image first with --ansible-build"
|
||||
exit 1
|
||||
else
|
||||
echo "I just attempted to run the image $IMAGE_NAME, but I could not because it doesn't exist on your system."
|
||||
exit 1
|
||||
fi;
|
||||
fi
|
||||
|
||||
# Always create a new container if this flag is set.
|
||||
# This stops any previously running containers. If none are running, then move on.
|
||||
if [ "${DOCKER_FORCE_NEW}" == "1" ]; then
|
||||
docker_stop $CONTAINER_NAME
|
||||
fi
|
||||
|
||||
# Run the image in a container if it's not already running.
|
||||
if [ $( docker ps | grep $CONTAINER_NAME | wc -l ) == 0 ]; then
|
||||
echo "Running docker image ${IMAGE_NAME} in container ${CONTAINER_NAME} ..."
|
||||
docker run \
|
||||
--rm \
|
||||
--detach \
|
||||
--network host \
|
||||
$CONFIG_DOCKER_MOUNTS \
|
||||
$CONFIG_DOCKER_ENV \
|
||||
--name $CONTAINER_NAME \
|
||||
$DOCKER_OPTIONS \
|
||||
$IMAGE_NAME \
|
||||
$COMMAND
|
||||
else
|
||||
echo "Docker image ${IMAGE_NAME} already running in container ${CONTAINER_NAME}."
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
# Same as docker_run_detach() but do not check if the image exists. This works only if the image is
|
||||
# publicly available or in a repo that we have access to. Docker will just fetch the image automatically,
|
||||
# whereas docker_run_detach() will throw an error if it doesn't exst locally. Ugh.
|
||||
# $1 docker image name to run
|
||||
# $2 name of the container
|
||||
# $3 command to run. Defaults to sleep infinity
|
||||
#
|
||||
# Set the variable DOCKER_OPTIONS with any custom options you want, and we'll pass this to the docker
|
||||
# program verbatim.
|
||||
#
|
||||
# Set the variable DOCKER_FORCE_NEW=1 to always start a new container each time. The default is to re-use
|
||||
# already running containers.
|
||||
#
|
||||
docker_run_detach_nocheck()
|
||||
{
|
||||
IMAGE_NAME=$1
|
||||
CONTAINER_NAME=$2
|
||||
if [[ -z "$3" ]]; then
|
||||
COMMAND="sleep infinity"
|
||||
else
|
||||
COMMAND=$3
|
||||
fi
|
||||
|
||||
# Always create a new container if this flag is set.
|
||||
# This stops any previously running containers. If none are running, then move on.
|
||||
if [ "${DOCKER_FORCE_NEW}" == "1" ]; then
|
||||
docker_stop $CONTAINER_NAME
|
||||
fi
|
||||
|
||||
# Run the image in a container if it's not already running.
|
||||
if [ $( docker ps | grep $CONTAINER_NAME | wc -l ) == 0 ]; then
|
||||
echo "Running docker image ${IMAGE_NAME} in container ${CONTAINER_NAME} ..."
|
||||
docker run \
|
||||
--rm \
|
||||
--detach \
|
||||
--network host \
|
||||
$CONFIG_DOCKER_MOUNTS \
|
||||
$CONFIG_DOCKER_ENV \
|
||||
--name $CONTAINER_NAME \
|
||||
$DOCKER_OPTIONS \
|
||||
$IMAGE_NAME \
|
||||
$COMMAND
|
||||
else
|
||||
echo "Docker image ${IMAGE_NAME} already running in container ${CONTAINER_NAME}."
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
# Stop a docker container
|
||||
docker_stop()
|
||||
{
|
||||
CONTAINER_NAME=$1
|
||||
if [ $(docker container ls | grep $CONTAINER_NAME | wc -l) -ge 1 ]; then
|
||||
echo "Stopping docker container ${CONTAINER_NAME}"
|
||||
docker stop $CONTAINER_NAME
|
||||
fi
|
||||
}
|
||||
Executable
+191
@@ -0,0 +1,191 @@
|
||||
#!/bin/bash
|
||||
# @author Craig McDaniel
|
||||
#
|
||||
# Fontend script to docker compose
|
||||
#
|
||||
# This is how we run various services in development environments for development.
|
||||
#
|
||||
|
||||
INCLUDE_DIR="/opt/neutopia/git/devops/orchestrate/lib"
|
||||
|
||||
# Read in libs
|
||||
source ${INCLUDE_DIR}/lib.sh
|
||||
source ${INCLUDE_DIR}/build-lib.sh
|
||||
|
||||
# Set some default values. We'll fill these out a few lines down.
|
||||
COMMAND=""
|
||||
COMPOSE_FILE=""
|
||||
AUTO_PREPARE=1
|
||||
|
||||
# If the user specifies this flag, then don't run the prepare Ansible playbooks.
|
||||
if [[ $@ =~ "--no-prepare" ]]; then
|
||||
AUTO_PREPARE=0
|
||||
fi
|
||||
|
||||
# Use getopts to get the value of the -f argument so we know what compose file to use.
|
||||
OPTERR=0
|
||||
while getopts "c:y:" OPTION $@;
|
||||
do
|
||||
if [ "${OPTION}" == "c" ]; then
|
||||
COMMAND=$OPTARG
|
||||
elif [ "${OPTION}" == "y" ]; then
|
||||
COMPOSE_FILE=$OPTARG
|
||||
fi
|
||||
done
|
||||
|
||||
# Build the $DOCKERARGS variable. Exclude any options that we don't want to pass directly to the
|
||||
# docker-compose script. When we're done, this string will be passed literally to docker-compose.
|
||||
ARGSORIG=($@)
|
||||
DOCKER_COMMAND_ARGS=""
|
||||
i=0
|
||||
while [ $i -lt 25 ]; do
|
||||
# Skip the next 2 args: the arg and the value.
|
||||
if [ "${ARGSORIG[$i]}" == "-c" ]; then
|
||||
((i=i+2))
|
||||
# Skip the next 2 args: the arg and the value.
|
||||
elif [ "${ARGSORIG[$i]}" == "-y" ]; then
|
||||
((i=i+2))
|
||||
# Skip the next arg.
|
||||
elif [ "${ARGSORIG[$i]}" == "--no-prepare" ]; then
|
||||
((i=i+1))
|
||||
else
|
||||
DOCKER_COMMAND_ARGS="${DOCKER_COMMAND_ARGS} ${ARGSORIG[$i]}"
|
||||
((i++))
|
||||
fi;
|
||||
done
|
||||
|
||||
# docker-compose expects arguments in this order
|
||||
DOCKERARGS="-f ${COMPOSE_FILE} ${COMMAND} ${DOCKER_COMMAND_ARGS}"
|
||||
|
||||
# Set these ENV variables so we can use them inside the compose YAML files
|
||||
# Get the image names
|
||||
|
||||
# whmcsphp
|
||||
export BILLING_APACHE2_TAG=`cd /opt/neutopia/git/whmcsphp; git log -n 1 --pretty=format:"%H" .`
|
||||
export BILLING_APACHE2_IMAGE_NAME="billing-apache2:${BILLING_APACHE2_TAG}"
|
||||
export BILLING_PHPFPM_TAG=`cd /opt/neutopia/git/whmcsphp; git log -n 1 --pretty=format:"%H" .`
|
||||
export BILLING_PHPFPM_IMAGE_NAME="billing-phpfpm:${BILLING_PHPFPM_TAG}"
|
||||
|
||||
# You have to do this in order for docker-compose to be able to use $HOSTNAME
|
||||
export HOSTNAME=$HOSTNAME
|
||||
|
||||
# Show help text
|
||||
show_help()
|
||||
{
|
||||
echo
|
||||
echo "Run services in a development environment using docker compose."
|
||||
echo
|
||||
echo "Usage: "
|
||||
echo "$0 -c <command> -y <compose-yaml-file> [command-options]"
|
||||
echo
|
||||
echo "Options that are used by this script only:"
|
||||
echo " -c The command to pass to docker compose. 'run', 'start', 'stop', 'logs', so on..."
|
||||
echo " -y Specify compose YAML file to use."
|
||||
echo " --no-prepare Optionally. Do not run the Ansible prepare playbook. You will do the preparing yourself!"
|
||||
echo
|
||||
echo "Commands are as follows:"
|
||||
echo " prepare Run the Ansible prepare playbook to prepare the dev environment for the matching compose YML file."
|
||||
echo " up Bring all services up and connect stdin/stdout to it."
|
||||
echo " logs View your container logs. Combine with -f to continually display logs as they are generated."
|
||||
echo " down Bring services down."
|
||||
echo " * Run docker compose --help for an exhaustive list of commands."
|
||||
echo
|
||||
echo "Command options are passed directly to docker-compose and depend on the command."
|
||||
echo " * For an example of options to the 'up' command, run docker compose up --help"
|
||||
echo " * For an example of options to the 'down' command, run docker compose down --help"
|
||||
echo " * And so on ..."
|
||||
echo
|
||||
}
|
||||
|
||||
# Show help?
|
||||
if [[ $@ =~ "--help" ]]; then
|
||||
show_help
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Main entry point.
|
||||
main()
|
||||
{
|
||||
if [ "${COMMAND}" = "build" ]; then
|
||||
echo
|
||||
echo "The build command is not supported here. You must use the build.sh script to build images.";
|
||||
echo
|
||||
exit 1
|
||||
elif [ "${COMMAND}" = "prepare" ]; then
|
||||
check_for_valid_args
|
||||
prepare
|
||||
elif [ "${COMMAND}" != "" ]; then
|
||||
check_for_valid_args
|
||||
echo "Using compose file: ${COMPOSE_FILE}"
|
||||
#prepare
|
||||
docker compose $DOCKERARGS
|
||||
else
|
||||
show_help
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
# Make sure the docker compose file and the command are both specified. Show error messages if not.
|
||||
check_for_valid_args()
|
||||
{
|
||||
if [ -z $COMMAND ]; then
|
||||
echo "No command was specified. Please specify a command to pass to docker compose with -c"
|
||||
echo " --help for details."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z $COMPOSE_FILE ]; then
|
||||
echo "Please specify a docker compose file with the -y argument. None was specified."
|
||||
echo " --help for details."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
# ** CURRENTLY NOT USED **
|
||||
# Run the correct ansible playbook to prepare the environment, depending on what compose file we're running.
|
||||
# If --no-prepare was specified, we don't execute this.
|
||||
prepare()
|
||||
{
|
||||
# Only prepare if AUTO_PREPARE=1
|
||||
if [ "${AUTO_PREPARE}" != 1 ]; then
|
||||
return
|
||||
fi
|
||||
|
||||
# Only run prepare for 'prepare', 'up' and 'start' commands.
|
||||
if [[ "${COMMAND}" != "prepare" && "${COMMAND}" != "up" && "${COMMAND}" != "start" ]]; then
|
||||
return
|
||||
fi
|
||||
|
||||
if [ "${COMPOSE_FILE}" = "docker-compose-one.yml" ]; then
|
||||
prepare_billing
|
||||
elif [ "${COMPOSE_FILE}" = "docker-compose-two.yml" ]; then
|
||||
prepare_hehe
|
||||
if [ $? != 0 ]; then
|
||||
echo
|
||||
echo "Just tried to create a docker container with docker image '${IMAGE_NAME}', but that operation failed."
|
||||
echo "You may need to build the apiserver image again if you have increased the borgdrone SVN revision since the last time you built the image.";
|
||||
echo "Run 'docker image ls' to see what tags you have for the appserver image, if any."
|
||||
exit $?;
|
||||
fi
|
||||
else
|
||||
echo "Can't prepare anything because I don't know that docker compose YML file ${COMPOSE_FILE}. Make sure you edit run.sh and add the code for this compose file."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
# ** CURRENTLY NOT USED **
|
||||
# Prepare the the billing system to run in a dev environment.
|
||||
prepare_billing()
|
||||
{
|
||||
ansible_playbook playbooks/build/prepare_billing.yml
|
||||
if [ $? != 0 ]; then exit $?; fi
|
||||
docker_stop apiserver-php
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
# Start the script
|
||||
main
|
||||
Reference in New Issue
Block a user