Skip to content

Instantly share code, notes, and snippets.

@loopyd
Created April 15, 2024 08:29
Show Gist options
  • Save loopyd/22159a7e341e9842662ad17f26f73fab to your computer and use it in GitHub Desktop.
Save loopyd/22159a7e341e9842662ad17f26f73fab to your computer and use it in GitHub Desktop.
[DeiDog] Docker Management API
#!/bin/bash
# @file deicog/docker.sh
# @brief A shell script API to manage Docker resources.
# @description This script is a wrapping API used to manage Docker resources like networks, swarms, services, stacks, containers, images, and volumes. It can be sourced as a library, or used as a command-line tool.
# @author Robert Smith <loopyd@github.com>
# @license MIT License
# @version 0.1
# Shell configuration
shopt -s extglob
set -Eeo pipefail
# Global variables
DEBUG=${DEBUG:-true}
ACTION=${ACTION:-}
SUBACTION=${SUBACTION:-}
BARGS=($*)
CSCRIPT_DIR=$(dirname "$0")
# Colors - Internally used for printing messages
C_DARK_WHITE="\033[0;30m"
C_WHITE="\033[0;37m"
C_YELLOW="\033[0;33m"
C_RED="\033[0;31m"
C_BLUE="\033[0;34m"
C_GREEN="\033[0;32m"
C_BOLD_WHITE="\033[1;37m"
C_BOLD_YELLOW="\033[1;33m"
C_BOLD_RED="\033[1;31m"
C_BOLD_BLUE="\033[1;34m"
C_BOLD_GREEN="\033[1;32m"
C_RESET="\033[0m"
# @brief Display a debug message
# @param $1 The message to display
# @return void
function debug() {
if [ "$DEBUG" = true ]; then
echo -e "${C_DARK_WHITE}$(date +"%Y-%m-%d %H:%M:%S")${C_RESET} ${C_WHITE}[${C_RESET}${C_BOLD_WHITE}DEBUG ${C_RESET}${C_WHITE}]${C_RESET} ${C_WHITE}$1${C_RESET}" >&2
fi
}
# @brief Display a warning message
# @param $1 The message to display
# @return void
function warn() {
echo -e "${C_DARK_WHITE}$(date +"%Y-%m-%d %H:%M:%S")${C_RESET} ${C_YELLOW}[${C_RESET}${C_BOLD_YELLOW}WARNING${C_RESET}${C_YELLOW}]${C_RESET} ${C_YELLOW}$1${C_RESET}" >&2
}
# @brief Display an error message
# @param $1 The message to display
# @return void
function err() {
echo -e "${C_DARK_WHITE}$(date +"%Y-%m-%d %H:%M:%S")${C_RESET} ${C_RED}[${C_RESET}${C_BOLD_RED}ERROR ${C_RESET}${C_RED}]${C_RESET} ${C_RED}$1${C_RESET}" >&2
}
# @brief Display an informational message
# @param $1 The message to display
# @return void
function info() {
local C_RESET="\033[0m"
echo -e "${C_DARK_WHITE}$(date +"%Y-%m-%d %H:%M:%S")${C_RESET} ${C_BLUE}[${C_RESET}${C_BOLD_BLUE}INFO ${C_RESET}${C_BLUE}]${C_RESET} ${C_BLUE}$1${C_RESET}"
}
# @brief Display a success message
# @param $1 The message to display
# @return void
function success() {
local C_RESET="\033[0m"
echo -e "${C_DARK_WHITE}$(date +"%Y-%m-%d %H:%M:%S")${C_RESET} ${C_GREEN}[${C_RESET}${C_BOLD_GREEN}SUCCESS${C_RESET}${C_GREEN}]${C_RESET} ${C_GREEN}$1${C_RESET}"
}
# @brief Function to detect if the script is being sourced
# @param $1 The action to display
# @return void
function __is_script_sourced() {
if [[ "${BASH_SOURCE[0]}" != "$0" ]]; then
return 0
else
return 1
fi
}
# @brief Exit trap function
# @return void
function __exit_trap() {
local exit_code=$?
if [[ $exit_code -ne 0 ]]; then
err "Error: Process exited with status code: $exit_code"
else
success "$0 exited successfully"
fi
unset BUILDKIT_PROGRESS || true
cd "$CSCRIPT_PATH"
exit $exit_code
}
# @brief Runs a command, logs the output, and displays useful debugging information.
# @param $* The command to run, and its arguments
# @return exit code of the command
function __run() {
if [ "$DEBUG" = true ]; then
local _env_before
_env_before=$(printenv | sort)
debug "Running: $*"
eval "$*" || {
return $?
}
local _env_after
_env_after=$(printenv | sort)
local _env_diff
_env_diff=$(diff <(echo "$_env_before") <(echo "$_env_after") | grep '^[<>]' | sed 's/^< //;s/^> //')
if [[ -n "$_env_diff" ]]; then
debug "Environment Changes: $_env_diff"
fi
else
eval "$* >/dev/null 2>&1" || {
return $?
}
fi
}
# @brief Remove a directory safely with sudo
# @param $1 The directory to remove
# @return 1 if the directory could not be removed, 0 otherwise
function __safe_rmdir() {
local DIR="$1"
if [ -d "$DIR" ]; then
sudo rm -rfv "$DIR" || {
sudo chown -R $(whoami) "$DIR"
sudo chmod -R u+rww "$DIR"
sudo rm -rfv "$DIR" || {
err "Failed to remove directory $DIR"
return 1
}
}
else
warning "Directory $DIR does not exist"
return 0
fi
}
# @brief Check if Docker Swarm mode is initialized
# @return 1 if docker swarm is initialized, otherwise 0
function __is_docker_swarm_initialized() {
if [ "$(docker info --format '{{.Swarm.LocalNodeState}}')" == "inactive" ]; then
return 1
else
return 0
fi
}
# @brief Check if a Docker network exists
# @param $1 The network name to check
# @return 1 if the network does not exist, otherwise 0
function __docker_network_exists() {
local NETWORK_NAME="$1"
if [ -z "$NETWORK_NAME" ]; then
err "NETWORK_NAME is required"
return 1
fi
local NODE_ID
NODE_ID=$(docker info --format '{{.Swarm.NodeID}}')
if [ -z "$NODE_ID" ]; then
return 1
fi
local NETWORK_ID
NETWORK_ID=$(docker network ls -q --filter name="$NETWORK_NAME" --format="{{.Name}}" | tr -d '\n')
if [ "$NETWORK_ID" != "$NETWORK_NAME" ]; then
return 1
else
return 0
fi
}
# @brief Check if a Docker container exists
# @param $1 The container name to check
# @return 1 if the container does not exist, otherwise 0
function __docker_container_exists() {
local CONTAINER_NAME="$1"
if [ -z "$CONTAINER_NAME" ]; then
err "CONTAINER_NAME is required"
return 1
fi
local CONTAINER_ID
CONTAINER_ID=$(docker container ps -a --format '{{ .Image }}' | grep -E "^$CONTAINER_NAME$")
if [ "$CONTAINER_ID" != "$CONTAINER_NAME" ]; then
return 1
else
return 0
fi
}
# @brief Check if a Docker volume exists
# @param $1 The volume name to check
# @return 1 if the volume does not exist, otherwise 0
function __docker_volume_exists() {
local VOLUME_NAME="$1"
if [ -z "$VOLUME_NAME" ]; then
err "VOLUME_NAME is required"
return 1
fi
local VOLUME_ID
VOLUME_ID=$(docker volume ls --filter name="$VOLUME_NAME" --format "{{.Name}}" | tr -d '\n')
if [ "$VOLUME_ID" != "$VOLUME_NAME" ]; then
return 1
else
return 0
fi
}
# @brief Check if a Docker service exists
# @param $1 The service ID to check
# @return 1 if the service does not exist, otherwise 0
function __docker_service_exists() {
local SERVICE_NAME="$1"
if [ -z "$SERVICE_NAME" ]; then
err "SERVICE_NAME is required"
return 1
fi
local NODE_ID
NODE_ID=$(docker info --format '{{.Swarm.NodeID}}')
if [ -z "$NODE_ID" ]; then
return 1
fi
local SERVICE_ID
SERVICE_IDS=$(docker service ls --format "{{.ID}}" | tr -d '\n' | grep -qE "^$SERVICE_NAME$")
if [[ "$SERVICE_ID" = *"$SERVICE_NAME"* ]]; then
return 1
else
return 0
fi
}
# @brief Check if a Docker stack exists
# @param $1 The stack name to check
# @return 1 if the stack does not exist, otherwise 0
function __docker_stack_exists() {
local STACK_NAME="$1"
if [ -z "$STACK_NAME" ]; then
err "STACK_NAME is required"
return 1
fi
local STACK_ID
STACK_ID=$(docker stack ls --format "{{.Name}}" | grep -E "^$STACK_NAME$" | tr -d '\n')
if [ "$STACK_ID" != "$STACK_NAME" ]; then
return 1
else
return 0
fi
}
# @brief Check if a Docker image exists
# @param $1 The image name to check
# @return 1 if the image does not exist, otherwise 0
function __docker_image_exists() {
local IMAGE_NAME
IMAGE_NAME="$1"
if [ -z "$IMAGE_NAME" ]; then
err "IMAGE_NAME is required"
return 1
fi
local IMAGE_ID
IMAGE_ID=$(docker image ls --filter reference="$IMAGE_NAME" --format "{{.Repository}}:{{.Tag}}" | grep -E "^$IMAGE_NAME")
if [ -z "$IMAGE_ID" ]; then
return 1
else
return 0
fi
}
####################################################################################################
# Swarm Management
####################################################################################################
# @brief Check if a Docker swarm is initialized
# @return 1 If the swarm could not be initialized, otherwise 0
function docker_swarm_init() {
if ! __is_docker_swarm_initialized; then
info "Initializing Docker Swarm mode: $(hostname) @ ${IP_ADDRESS}..."
local IP_ADDRESS
IP_ADDRESS=$(hostname -I | cut -d' ' -f1)
debug "IP_ADDRESS: $IP_ADDRESS"
__run docker swarm init \
--advertise-addr "$IP_ADDRESS" || {
err "Failed to initialize Docker Swarm mode."
return 1
}
success "Docker Swarm mode initialized successfully."
return 0
else
warn "Docker Swarm mode is already initialized."
return 0
fi
}
# @brief Leave a Docker Swarm mode
# @return 1 if the swarm could not be left, otherwise 0
function docker_swarm_leave() {
info "Leaving Docker Swarm mode..."
if ! __is_docker_swarm_initialized; then
warn "Docker Swarm mode is not initialized, not leaving swarm."
return 0
fi
local TIMEOUT=0
while __is_docker_swarm_initialized && [ $TIMEOUT -lt 5 ]; do
__run docker swarm leave --force || true
sleep 1s
TIMEOUT=$((TIMEOUT + 1))
done
if [ $TIMEOUT -ge 5 ]; then
err "Timeout occoured while trying to leave Docker Swarm mode."
return 1
else
success "Docker Swarm mode left successfully."
return 0
fi
}
####################################################################################################
# Stack Management
####################################################################################################
# @brief This function deploys a Docker Stack
# @param $* The arguments to pass to the docker stack deploy command
# @return 1 if the stack could not be deployed, otherwise 0
function docker_stack_deploy() {
local FARGS=($*)
if [ ${#FARGS[@]} -lt 1 ]; then
err "STACK_NAME is required as the last argument"
return 1
fi
local STACK_NAME="${FARGS[-1]}"
if ! __is_docker_swarm_initialized; then
err "Docker Swarm mode is not initialized."
return 1
fi
if ! __docker_stack_exists "$STACK_NAME"; then
info "Deploying stack: $STACK_NAME..."
__run docker stack deploy ${FARGS[@]} || {
err "Failed to deploy stack: $STACK_NAME"
return 1
}
else
warn "Manager stack: $STACK_NAME already exists."
return 0
fi
success "Docker Swarm initialization is complete."
return 0
}
# @brief This function removes a Docker Stack
# @param $* The arguments to pass to the docker stack rm command
# @return 1 if the stack could not be removed, otherwise 0
function docker_stack_remove() {
local FARGS=($*)
if [ ${#FARGS[@]} -lt 1 ]; then
err "STACK_NAME is required as the last argument"
return 1
fi
local STACK_NAME="${FARGS[-1]}"
if ! __is_docker_swarm_initialized; then
warn "Docker Swarm mode is not initialized, not bringing down stack: $STACK_NAME."
return 1
fi
if ! __docker_stack_exists "$STACK_NAME"; then
warn "Stack: $STACK_NAME does not exist, no action taken."
return 0
fi
info "Removing stack: $STACK_NAME..."
local TIMEOUT=0
while __docker_stack_exists "$STACK_NAME" && [ $TIMEOUT -lt 5 ]; do
__run docker stack rm ${FARGS[@]} || true
sleep 1s
TIMEOUT=$((TIMEOUT + 1))
done
if [ $TIMEOUT -ge 5 ]; then
err "Timeout occoured while trying to remove stack: $STACK_NAME"
return 1
else
success "Docker Stack removal is complete."
return 0
fi
}
####################################################################################################
# Network Management
####################################################################################################
# @brief This function creates a Docker network
# @param $* The arguments to pass to the docker network create command
# @return 1 if the network could not be created, otherwise 0
function docker_network_create() {
local FARGS=($*)
local NETWORK_NAME="${FARGS[-1]}"
if [ -z "$NETWORK_NAME" ]; then
err "NETWORK_NAME is required"
return 1
fi
local TIMEOUT=0
while ! __docker_network_exists "$NETWORK_NAME" && [ $TIMEOUT -lt 5 ]; do
__run docker network create ${FARGS[@]} || true
sleep 1s
TIMEOUT=$((TIMEOUT + 1))
done
if [ $TIMEOUT -ge 5 ]; then
err "Timeout occoured while trying to create network: $NETWORK_NAME"
return 1
else
success "Network: $NETWORK_NAME created successfully."
return 0
fi
}
# This function removes a Docker network
# @param $1 The network name to remove
# @return 1 if the network could not be removed, otherwise 0
function docker_network_remove() {
local NETWORK_NAME="$1"
if [ -z "$NETWORK_NAME" ]; then
err "NETWORK_NAME is required"
return 1
fi
debug "NETWORK_NAME: $NETWORK_NAME"
if __docker_network_exists "$NETWORK_NAME"; then
local _endpointNames=()
mapfile -t _endpointNames < <(docker network inspect "$_network" --format="{{range .Containers}}{{.Name}} {{end}}" | sed 's/ /\n/g')
for _endpointName in "${_endpointNames[@]}"; do
if [ -z "$_endpointName" ]; then
continue
fi
info "Disconnecting network: $_network from endpoint: $_endpointName..."
__run docker network disconnect --force "$_network" "$_endpointName" || {
err "Failed to disconnect network: $_network from endpoint: $_endpointName"
return 1
}
done
info "Trying to remove network: $_network..."
local TIMEOUT=0
while __docker_network_exists "$_network" && [ $TIMEOUT -lt 5 ]; do
__run docker network rm "$_network" || true
sleep 1s
done
if [ $TIMEOUT -ge 5 ]; then
err "Timeout occoured while trying to remove network: $_network"
return 1
else
success "Network: $_network went down successfully."
return 0
fi
else
warn "Network: $NETWORK_NAME does not exist."
return 0
fi
success "Network: $NETWORK_NAME went down successfully."
return 0
}
# @brief This function removes all the Docker networks specified
# @param $* The arguments to pass to the docker network ls command (for filtering)
# @return 1 if the networks could not be removed, otherwise 0
function docker_networks_remove() {
local FARGS=($*)
local _networks=()
mapfile -t _networks < <(docker network ls -q ${FARGS[*]} --format="{{.Name}}")
if [ ${#_networks[@]} -eq 0 ]; then
warn "No networks found to remove, no action taken."
return 0
fi
local FAILED=0
for _network in "${_networks[@]}"; do
if [ -z "$_network" ] || [ "$_network" == "bridge" ] || [ "$_network" == "host" ] || [ "$_network" == "none" ]; then
continue
fi
docker_network_remove "$_network" || {
FAILED=$((FAILED + 1))
}
done
if [ $FAILED -gt 0 ]; then
err "Failed to remove ${FAILED} network(s)."
return 1
else
success "All networks went down successfully."
return 0
fi
}
####################################################################################################
# Service Management
####################################################################################################
# @brief This function creates a Docker service
# @param $* The arguments to pass to the docker service create command
# @return 1 if the service could not be created, otherwise 0
function docker_service_create() {
local FARGS=($*)
if [ ${#FARGS[@]} -lt 1 ]; then
err "SERVICE_NAME is required as the last argument"
return 1
fi
local SERVICE_NAME="${FARGS[-1]}"
if ! __docker_service_exists "$SERVICE_NAME"; then
info "Creating service: $SERVICE_NAME..."
__run docker service create ${FARGS[@]} || {
err "Failed to create service: $SERVICE_NAME"
return 1
}
success "Service: $SERVICE_NAME created successfully."
return 0
else
warn "Service: $SERVICE_NAME already exists."
return 0
fi
}
# @brief This function removes a Docker service
# @param $* The arguments to pass to the docker service rm command
# @return 1 if the service could not be removed, otherwise 0
function docker_service_remove() {
local FARGS=($*)
if [ ${#FARGS[@]} -lt 1 ]; then
err "SERVICE_NAME is required as the last argument"
return 1
fi
local SERVICE_NAME="${FARGS[-1]}"
debug "SERVICE_NAME: $SERVICE_NAME"
if __docker_service_exists "$SERVICE_NAME"; then
info "Removing service: $SERVICE_NAME..."
__run docker service rm ${FARGS[@]} || {
err "Failed to remove service: $SERVICE_NAME"
return 1
}
else
warn "Service: $SERVICE_NAME does not exist."
return 0
fi
success "Service: $SERVICE_NAME went down successfully."
return 0
}
# @brief This function removes all the Docker services specified
# @param $* The arguments to pass to the docker service ls command (for filtering)
# @return 1 if the services could not be removed, otherwise 0
function docker_services_remove() {
local FARGS=($*)
local _services=()
mapfile -t _services < <(docker service ls ${FARGS[@]} --format="{{.ID}}")
if [ ${#_services[@]} -eq 0 ]; then
warn "No services found to remove, no action taken."
return 0
fi
local _failed=0
for _service in "${_services[@]}"; do
if [ -z "$_service" ]; then
continue
fi
docker_service_remove "$_service" || {
_failed=$((_failed + 1))
}
done
if [ $_failed -gt 0 ]; then
err "Failed to remove ${_failed} service(s)."
return 1
else
success "All services went down successfully."
return 0
fi
}
####################################################################################################
# Volume Management
####################################################################################################
# @brief This function removes all the Docker volumes specified
# @param $* The arguments to pass to the docker volume ls command (for filtering)
# @return 1 if the volumes could not be removed, otherwise 0
function docker_volumes_remove() {
local FARGS=($*)
local _volumes=()
mapfile -t _volume < <(docker volume ls ${FARGS[@]} --format '{{.Name}}')
local _failed=0
for _volume in "${_volumes[@]}"; do
if [ -z "$_volume" ]; then
continue
fi
info "Removing volume: $_volume..."
__run docker volume rm "$_volume" || {
err "Failed to remove volume: $_volume"
_failed=$((_failed + 1))
}
done
if [ $_failed -gt 0 ]; then
err "Failed to remove ${_failed} volume(s)."
return 1
else
success "All volumes went down successfully."
return 0
fi
}
####################################################################################################
# Image Management
####################################################################################################
# @brief This function removes all the Docker images specified
# @param $* The arguments to pass to the docker image ls command (for filtering)
# @return 1 if the images could not be removed, otherwise 0
function docker_images_remove() {
local FARGS=($*)
local _images=()
mapfile -t _images < <(docker image ls ${FARGS[@]} --format '{{.ID}}')
local _failed=0
if [ ${#_images[@]} -eq 0 ]; then
warn "No images found to remove, no action taken."
return 0
fi
for _image in "${_images[@]}"; do
if [ -z "$_image" ]; then
continue
fi
info "Removing image: $_image..."
__run docker rmi "$_image" || {
err "Failed to remove image: $_image"
_failed=$((_failed + 1))
}
done
if [ $_failed -gt 0 ]; then
err "Failed to remove ${_failed} image(s)."
return 1
else
success "All images went down successfully."
return 0
fi
}
####################################################################################################
# Container Management
####################################################################################################
# @brief This function removes all the Docker containers specified
# @param $* The arguments to pass to the docker container ls command (for filtering)
# @return 1 if the containers could not be removed, otherwise 0
function docker_containers_remove() {
local FARGS=($*)
local _containers=()
mapfile -t _containers < <(docker container ls ${FARGS[@]} --format '{{.ID}}')
local _failed=0
if [ ${#_containers[@]} -eq 0 ]; then
warn "No containers found to remove, no action taken."
return 0
fi
for _container in "${_containers[@]}"; do
if [ -z "$_container" ]; then
continue
fi
info "Removing container: $_container..."
__run docker rm "$_container" || {
err "Failed to remove container: $_container"
_failed=$((_failed + 1))
}
done
if [ $_failed -gt 0 ]; then
err "Failed to remove ${_failed} container(s)."
return 1
else
success "All containers went down successfully."
return 0
fi
}
# @brief This function commits changes from a Docker container to an image
# @param $1 The container name to commit
# @param $2 The image name to commit to
# @return 1 if the container could not be committed, otherwise 0
function docker_container_commit() {
local CONTAINER_NAME="$1"
if [ -z "$CONTAINER_NAME" ]; then
err "CONTAINER_NAME is required"
return 1
fi
local IMAGE_NAME="$2"
if [ -z "$IMAGE_NAME" ]; then
err "IMAGE_NAME is required"
return 1
fi
if ! __docker_image_exists "$IMAGE_NAME"; then
err "Image: $IMAGE_NAME does not exist."
return 1
fi
local CONTAINER_ID
CONTAINER_ID=$(docker container ps -a --filter name="$CONTAINER_NAME" --format "{{.ID}}" | head -n1)
debug "CONTAINER_ID: $CONTAINER_ID"
if [ -z "$CONTAINER_ID" ]; then
err "Container: $CONTAINER_NAME does not exist."
return 1
fi
info "Committing changes from container: $CONTAINER_NAME to image: $IMAGE_NAME..."
__run docker commit "$CONTAINER_ID" "$IMAGE_NAME" || return 1
__run docker container rm "$CONTAINER_ID" || return 1
success "Changes from container: $CONTAINER_NAME committed to image: $IMAGE_NAME successfully."
return 0
}
####################################################################################################
# Main Script
####################################################################################################
# @brief This function displays the usage information for the interactive portion of the script
# @param $1 The action to display
# @param $2 The sub-action to display
# @return void
function usage() {
local MYACTION="$1"
shift 1 || true
local MYSUBACTION="$1"
shift 1 || true
echo -e "${C_BOLD_YELLOW}-----------------------------------------------------------------------------------${C_RESET}"
echo -e " ${C_BOLD_WHITE}Deity Docker Manager${C_RESET} - Docker Management Utilities API"
echo -e "${C_BOLD_YELLOW}-----------------------------------------------------------------------------------${C_RESET}"
echo ""
echo -e " ${C_BOLD_WHITE}Usage${C_RESET}"
echo ""
echo -e " $0 <action> <subaction> [options] [arguments]"
echo ""
echo -e " ${C_BOLD_WHITE}Global Options${C_RESET}"
echo ""
echo " --help Show this help message, and exit"
echo " --debug Enable debug mode"
echo ""
case "$MYACTION" in
swarm)
case "$MYSUBACTION" in
init)
echo -e " ${C_BOLD_WHITE}Options${C_RESET}"
echo ""
echo " No options for this action."
echo ""
;;
leave)
echo -e " ${C_BOLD_WHITE}Options${C_RESET}"
echo ""
echo " No options for this action."
echo ""
;;
*)
echo -e " ${C_BOLD_WHITE}Sub-Actions${C_RESET}"
echo ""
echo " init Initialize Docker Swarm mode"
echo " leave Leave Docker Swarm mode"
echo ""
;;
esac
;;
stack)
case "$MYSUBACTION" in
deploy)
echo -e " ${C_BOLD_WHITE}Options${C_RESET}"
echo ""
echo " No options for this action."
echo ""
;;
remove|rm)
echo -e " ${C_BOLD_WHITE}Options${C_RESET}"
echo ""
echo " No options for this action."
echo ""
;;
*)
echo -e " ${C_BOLD_WHITE}Sub-Actions${C_RESET}"
echo ""
echo " deploy Deploy a Docker Stack"
echo " remove Remove a Docker Stack"
echo ""
;;
esac
;;
stacks)
case "$MYSUBACTION" in
remove|rm)
echo -e " ${C_BOLD_WHITE}Options${C_RESET}"
echo ""
echo " No options for this action."
echo ""
;;
*)
echo -e " ${C_BOLD_WHITE}Sub-Actions${C_RESET}"
echo ""
echo " remove Remove all Docker Stacks"
echo ""
;;
esac
;;
network)
case "$MYSUBACTION" in
create)
echo -e " ${C_BOLD_WHITE}Options${C_RESET}"
echo ""
echo " No options for this action."
echo ""
;;
remove|rm)
echo -e " ${C_BOLD_WHITE}Options${C_RESET}"
echo ""
echo " No options for this action."
echo ""
;;
*)
echo -e " ${C_BOLD_WHITE}Sub-Actions${C_RESET}"
echo ""
echo " create Create a Docker Network"
echo " remove Remove a Docker Network"
echo ""
;;
esac
;;
networks)
case "$MYSUBACTION" in
remove|rm)
echo -e " ${C_BOLD_WHITE}Options${C_RESET}"
echo ""
echo " No options for this action."
echo ""
;;
*)
echo -e " ${C_BOLD_WHITE}Sub-Actions${C_RESET}"
echo ""
echo " remove Remove all Docker Networks"
echo ""
;;
esac
;;
service)
case "$MYSUBACTION" in
create)
echo -e " ${C_BOLD_WHITE}Options${C_RESET}"
echo ""
echo " No options for this action."
echo ""
;;
remove|rm)
echo -e " ${C_BOLD_WHITE}Options${C_RESET}"
echo ""
echo " No options for this action."
echo ""
;;
*)
echo -e " ${C_BOLD_WHITE}Sub-Actions${C_RESET}"
echo ""
echo " create Create a Docker Service"
echo " remove Remove a Docker Service"
echo ""
;;
esac
;;
services)
case "$MYSUBACTION" in
remove|rm)
echo -e " ${C_BOLD_WHITE}Options${C_RESET}"
echo ""
echo " No options for this action."
echo ""
;;
*)
echo -e " ${C_BOLD_WHITE}Sub-Actions${C_RESET}"
echo ""
echo " remove Remove all Docker Services"
echo ""
;;
esac
;;
volume)
case "$MYSUBACTION" in
create)
echo -e " ${C_BOLD_WHITE}Options${C_RESET}"
echo ""
echo " No options for this action."
echo ""
;;
remove|rm)
echo -e " ${C_BOLD_WHITE}Options${C_RESET}"
echo ""
echo " No options for this action."
echo ""
;;
*)
echo -e " ${C_BOLD_WHITE}Sub-Actions${C_RESET}"
echo ""
echo " create Create a Docker Volume"
echo " remove Remove a Docker Volume"
echo ""
;;
esac
;;
volumes)
case "$MYSUBACTION" in
remove|rm)
echo -e " ${C_BOLD_WHITE}Options${C_RESET}"
echo ""
echo " No options for this action."
echo ""
;;
*)
echo -e " ${C_BOLD_WHITE}Sub-Actions${C_RESET}"
echo ""
echo " remove Remove all Docker Volumes"
echo ""
;;
esac
;;
image)
case "$MYSUBACTION" in
create)
echo -e " ${C_BOLD_WHITE}Options${C_RESET}"
echo ""
echo " No options for this action."
echo ""
;;
remove|rm)
echo -e " ${C_BOLD_WHITE}Options${C_RESET}"
echo ""
echo " No options for this action."
echo ""
;;
*)
echo -e " ${C_BOLD_WHITE}Sub-Actions${C_RESET}"
echo ""
echo " create Create a Docker Image"
echo " remove Remove a Docker Image"
echo ""
;;
esac
;;
images)
case "$MYSUBACTION" in
remove|rm)
echo -e " ${C_BOLD_WHITE}Options${C_RESET}"
echo ""
echo " No options for this action."
echo ""
;;
*)
echo -e " ${C_BOLD_WHITE}Sub-Actions${C_RESET}"
echo ""
echo " remove Remove all Docker Images"
echo ""
;;
esac
;;
container)
case "$MYSUBACTION" in
create)
echo -e " ${C_BOLD_WHITE}Options${C_RESET}"
echo ""
echo " No options for this action."
echo ""
;;
remove|rm)
echo -e " ${C_BOLD_WHITE}Options${C_RESET}"
echo ""
echo " No options for this action."
echo ""
;;
commit)
echo -e " ${C_BOLD_WHITE}Options${C_RESET}"
echo ""
echo " No options for this action."
echo ""
;;
*)
echo -e " ${C_BOLD_WHITE}Sub-Actions${C_RESET}"
echo ""
echo " create Create a Docker Container"
echo " remove Remove a Docker Container"
echo " commit Commit changes from a Docker Container to an Image"
echo ""
;;
esac
;;
containers)
case "$MYSUBACTION" in
remove|rm)
echo -e " ${C_BOLD_WHITE}Options${C_RESET}"
echo ""
echo " No options for this action."
echo ""
;;
*)
echo -e " ${C_BOLD_WHITE}Sub-Actions${C_RESET}"
echo ""
echo " remove Remove all Docker Containers"
echo ""
;;
esac
;;
*)
echo -e " ${C_BOLD_WHITE}Action (required)${C_RESET}"
echo ""
echo " swarm Manage Docker Swarm mode"
echo " stack Manage a Docker Stack"
echo " stacks Manage Docker Stacks"
echo " network Manage a Docker Network"
echo " networks Manage Docker Networks"
echo " service Manage a Docker Service"
echo " services Manage Docker Services"
echo " volume Manage a Docker Volume"
echo " volumes Manage Docker Volumes"
echo " image Manage a Docker Image"
echo " images Manage Docker Images"
echo " container Manage a Docker Container"
echo " containers Manage Docker Containers"
echo ""
;;
esac
echo -e " ${C_BOLD_WHITE}Additional Arguments${C_RESET}"
echo ""
echo " Any additional arguments will be passed to the action command."
echo ""
echo " For assistance with a specific action, use:"
echo ""
echo " $0 <action> --help"
echo ""
exit 0
}
# @brief Parse the command-line arguments and set the global variables for the interactive portion of the script
# @return void
function parse_args() {
if [ $# -eq 0 ]; then
usage
fi
ACTION="$1"
shift 1
case "$ACTION" in
swarm)
if [ $# -eq 0 ]; then
usage swarm
fi
if [[ ! "$1" =~ ^init|leave ]]; then
usage swarm
else
SUBACTION="$1"
shift 1
fi
case "$SUBACTION" in
init)
while [ $# -gt 0 ]; do
case "$1" in
-h | --help)
usage swarm init
;;
-d | --debug)
DEBUG=true
shift 1
;;
*)
BARGS+=("$1")
shift 1
break
;;
esac
done
;;
leave)
while [ $# -gt 0 ]; do
case "$1" in
-h | --help)
usage swarm leave
;;
-d | --debug)
DEBUG=true
shift 1
;;
*)
BARGS+=("$1")
shift 1
break
;;
esac
done
;;
*)
usage swarm
;;
esac
;;
stack)
if [ $# -eq 0 ]; then
usage stack
fi
if [[ ! "$1" =~ ^deploy|remove|rm ]]; then
usage stack
else
SUBACTION="$1"
shift 1
fi
case "$SUBACTION" in
deploy)
while [ $# -gt 0 ]; do
case "$1" in
-h | --help)
usage stack deploy
;;
-d | --debug)
DEBUG=true
shift 1
;;
*)
BARGS+=("$1")
shift 1
break
;;
esac
done
;;
remove|rm)
while [ $# -gt 0 ]; do
case "$1" in
-h | --help)
usage stack remove
;;
-d | --debug)
DEBUG=true
shift 1
;;
*)
BARGS+=("$1")
shift 1
break
;;
esac
done
;;
*)
usage stack
;;
esac
;;
stacks)
if [ $# -eq 0 ]; then
usage stacks
fi
if [[ ! "$1" =~ ^remove|rm ]]; then
usage stacks
else
SUBACTION="$1"
shift 1
fi
case "$SUBACTION" in
remove|rm)
while [ $# -gt 0 ]; do
case "$1" in
-h | --help)
usage stacks remove
;;
-d | --debug)
DEBUG=true
shift 1
;;
*)
BARGS+=("$1")
shift 1
break
;;
esac
done
;;
*)
usage stacks
;;
esac
;;
network)
if [ $# -eq 0 ]; then
usage network
fi
if [[ ! "$1" =~ ^create|remove|rm ]]; then
usage network
else
SUBACTION="$1"
shift 1
fi
case "$SUBACTION" in
create)
while [ $# -gt 0 ]; do
case "$1" in
-h | --help)
usage network create
;;
-d | --debug)
DEBUG=true
shift 1
;;
*)
BARGS+=("$1")
shift 1
break
;;
esac
done
;;
remove|rm)
while [ $# -gt 0 ]; do
case "$1" in
-h | --help)
usage network remove
;;
-d | --debug)
DEBUG=true
shift 1
;;
*)
BARGS+=("$1")
shift 1
break
;;
esac
done
;;
*)
usage network
;;
esac
;;
networks)
if [ $# -eq 0 ]; then
usage networks
fi
if [[ ! "$1" =~ ^remove|rm ]]; then
usage networks
else
SUBACTION="$1"
shift 1
fi
case "$SUBACTION" in
remove|rm)
while [ $# -gt 0 ]; do
case "$1" in
-h | --help)
usage networks remove
;;
-d | --debug)
DEBUG=true
shift 1
;;
*)
BARGS+=("$1")
shift 1
break
;;
esac
done
;;
*)
usage networks
;;
esac
;;
service)
if [ $# -eq 0 ]; then
usage service
fi
if [[ ! "$1" =~ ^create|remove|rm ]]; then
usage service
else
SUBACTION="$1"
shift 1
fi
case "$SUBACTION" in
create)
while [ $# -gt 0 ]; do
case "$1" in
-h | --help)
usage service create
;;
-d | --debug)
DEBUG=true
shift 1
;;
*)
BARGS+=("$1")
shift 1
break
;;
esac
done
;;
remove|rm)
while [ $# -gt 0 ]; do
case "$1" in
-h | --help)
usage service remove
;;
-d | --debug)
DEBUG=true
shift 1
;;
*)
BARGS+=("$1")
shift 1
break
;;
esac
done
;;
*)
usage service
;;
esac
;;
services)
if [ $# -eq 0 ]; then
usage services
fi
if [[ ! "$1" =~ ^remove|rm ]]; then
usage services
else
SUBACTION="$1"
shift 1
fi
case "$SUBACTION" in
remove|rm)
while [ $# -gt 0 ]; do
case "$1" in
-h | --help)
usage services remove
;;
-d | --debug)
DEBUG=true
shift 1
;;
*)
BARGS+=("$1")
shift 1
break
;;
esac
done
;;
*)
usage services
;;
esac
;;
container)
if [ $# -eq 0 ]; then
usage container
fi
if [[ ! "$1" =~ ^remove|rm|commit ]]; then
usage container
else
SUBACTION="$1"
shift 1
fi
case "$SUBACTION" in
remove|rm)
while [ $# -gt 0 ]; do
case "$1" in
-h | --help)
usage container remove
;;
-d | --debug)
DEBUG=true
shift 1
;;
*)
BARGS+=("$1")
shift 1
break
;;
esac
done
;;
commit)
while [ $# -gt 0 ]; do
case "$1" in
-h | --help)
usage container commit
;;
-d | --debug)
DEBUG=true
shift 1
;;
*)
BARGS+=("$1")
shift 1
break
;;
esac
done
;;
*)
usage container
;;
esac
;;
containers)
if [ $# -eq 0 ]; then
usage containers
fi
if [[ ! "$1" =~ ^remove|rm ]]; then
usage containers
else
SUBACTION="$1"
shift 1
fi
case "$SUBACTION" in
remove|rm)
while [ $# -gt 0 ]; do
case "$1" in
-h | --help)
usage containers remove
;;
-d | --debug)
DEBUG=true
shift 1
;;
*)
BARGS+=("$1")
shift 1
break
;;
esac
done
;;
*)
usage containers
;;
esac
;;
image)
if [ $# -eq 0 ]; then
usage image
fi
if [[ ! "$1" =~ ^remove|rm ]]; then
usage image
else
SUBACTION="$1"
shift 1
fi
case "$SUBACTION" in
remove|rm)
while [ $# -gt 0 ]; do
case "$1" in
-h | --help)
usage image remove
;;
-d | --debug)
DEBUG=true
shift 1
;;
*)
BARGS+=("$1")
shift 1
break
;;
esac
done
;;
*)
usage image
;;
esac
;;
images)
if [ $# -eq 0 ]; then
usage images
fi
if [[ ! "$1" =~ ^remove|rm ]]; then
usage images
else
SUBACTION="$1"
shift 1
fi
case "$SUBACTION" in
remove|rm)
while [ $# -gt 0 ]; do
case "$1" in
-h | --help)
usage images remove
;;
-d | --debug)
DEBUG=true
shift 1
;;
*)
BARGS+=("$1")
shift 1
break
;;
esac
done
;;
*)
usage images
;;
esac
;;
volume)
if [ $# -eq 0 ]; then
usage volume
fi
if [[ ! "$1" =~ ^create|remove|rm ]]; then
usage volume
else
SUBACTION="$1"
shift 1
fi
case "$SUBACTION" in
create)
while [ $# -gt 0 ]; do
case "$1" in
-h | --help)
usage volume create
;;
-d | --debug)
DEBUG=true
shift 1
;;
*)
BARGS+=("$1")
shift 1
break
;;
esac
done
;;
remove|rm)
while [ $# -gt 0 ]; do
case "$1" in
-h | --help)
usage volume remove
;;
-d | --debug)
DEBUG=true
shift 1
;;
*)
BARGS+=("$1")
shift 1
break
;;
esac
done
;;
*)
usage volume
;;
esac
;;
volumes)
if [ $# -eq 0 ]; then
usage volumes
fi
if [[ ! "$1" =~ ^remove|rm ]]; then
usage volumes
else
SUBACTION="$1"
shift 1
fi
case "$SUBACTION" in
remove|rm)
while [ $# -gt 0 ]; do
case "$1" in
-h | --help)
usage volumes remove
;;
-d | --debug)
DEBUG=true
shift 1
;;
*)
BARGS+=("$1")
shift 1
break
;;
esac
done
;;
*)
usage volumes
;;
esac
;;
-h | --help)
usage
;;
*)
usage
;;
esac
# Add remaining arguments to BARGS
while [ $# -gt 0 ]; do
BARGS+=("$1")
shift 1
done
}
# @brief Main function to handle all the actions
# @returns Error code if unsuccessful, 0 otherwise
function main() {
case $ACTION in
swarm)
case $SUBACTION in
init)
docker_swarm_init || return $?
;;
leave)
docker_swarm_leave || return $?
;;
*)
err "Invalid subaction: $SUBACTION"
usage $ACTION
;;
esac
;;
stack)
case $SUBACTION in
deploy)
docker_stack_deploy "${BARGS[@]}" || return $?
;;
remove|rm)
docker_stack_remove "${BARGS[@]}" || return $?
;;
*)
err "Invalid subaction: $SUBACTION"
usage $ACTION
;;
esac
;;
stacks)
case $SUBACTION in
remove|rm)
docker_stacks_remove "${BARGS[@]}" || return $?
;;
*)
err "Invalid subaction: $SUBACTION"
usage $ACTION
;;
esac
;;
network)
case $SUBACTION in
create)
docker_network_create "${BARGS[@]}" || return $?
;;
remove|rm)
docker_network_remove "${BARGS[@]}" || return $?
;;
*)
err "Invalid subaction: $SUBACTION"
usage $ACTION
;;
esac
;;
networks)
case $SUBACTION in
remove|rm)
docker_networks_remove "${BARGS[@]}" || return $?
;;
*)
err "Invalid subaction: $SUBACTION"
usage $ACTION
;;
esac
;;
service)
case $SUBACTION in
create)
docker_service_create "${BARGS[@]}" || return $?
;;
remove|rm)
docker_service_remove "${BARGS[@]}" || return $?
;;
*)
err "Invalid subaction: $SUBACTION"
usage $ACTION
;;
esac
;;
services)
case $SUBACTION in
remove|rm)
docker_services_remove "${BARGS[@]}" || return $?
;;
*)
err "Invalid subaction: $SUBACTION"
usage $ACTION
;;
esac
;;
container)
case $SUBACTION in
remove|rm)
docker_container_remove "${BARGS[@]}" || return $?
;;
commit)
docker_container_commit "${BARGS[@]}" || return $?
;;
*)
err "Invalid subaction: $SUBACTION"
usage $ACTION
;;
esac
;;
containers)
case $SUBACTION in
remove|rm)
docker_containers_remove "${BARGS[@]}" || return $?
;;
*)
err "Invalid subaction: $SUBACTION"
usage $ACTION
;;
esac
;;
image)
case $SUBACTION in
remove|rm)
docker_images_remove "${BARGS[@]}" || return $?
;;
*)
err "Invalid subaction: $SUBACTION"
usage $ACTION
;;
esac
;;
volume)
case $SUBACTION in
create)
docker_volume_create "${BARGS[@]}" || return $?
;;
remove|rm)
docker_volume_remove "${BARGS[@]}" || return $?
;;
*)
err "Invalid subaction: $SUBACTION"
usage $ACTION
;;
esac
;;
volumes)
case $SUBACTION in
remove|rm)
docker_volumes_remove "${BARGS[@]}" || return $?
;;
*)
err "Invalid subaction: $SUBACTION"
usage $ACTION
;;
esac
;;
*)
err "Invalid action: $ACTION"
usage
;;
esac
return 0
}
# If script is not being sourced, run the main function
if ! __is_script_sourced; then
trap __exit_trap EXIT
parse_args "$@"
main
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment