Skip to content

Instantly share code, notes, and snippets.

@nhalstead
Last active May 25, 2023 00:41
Show Gist options
  • Save nhalstead/c2932119a44f17f119d9282cfc555391 to your computer and use it in GitHub Desktop.
Save nhalstead/c2932119a44f17f119d9282cfc555391 to your computer and use it in GitHub Desktop.
Handy Bash Scripts for Development using docker containers in a namespace fashion built from a docker compose script using DockerStation and Kubernetes cluster.
# Bash Functions to load into the shell environment
alias chmox="chmod +x"
alias claer="clear"
alias exiut="exit"
alias exuit="exit"
alias exiot="exit"
alias exiout="exit"
alias exiit="exit"
mkcd () {
mkdir -p -- "$1" && cd -P -- "$1"
}
unload() {
RED='\033[0;31m'
GREEN='\033[1;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
if [[ -v L_PATH ]]; then
export PATH=$L_PATH
echo -e "${GREEN}Reset ENV${NC}"
fi
}
load() {
RED='\033[0;31m'
GREEN='\033[1;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# If an env already has been loaded, reset it
if [[ -v L_PATH ]]; then
export PATH=$L_PATH
echo -e "${RED}Reset ENV${NC}"
fi
# Save Last Path
export L_PATH=$PATH
# Uses Composer
if [ -f composer.json ]; then
export PATH="$(pwd)/vendor/bin;$PATH"
echo -e " ${YELLOW}Added: $(pwd)/vendor/bin${NC}"
fi
# NPM
if [ -f package.json ]; then
export PATH="$(pwd)/node_modules/.bin;$PATH"
echo -e " ${YELLOW}Added: $(pwd)/node_modules/.bin${NC}"
fi
# Local Bin Folder
if [ -d bin ]; then
export PATH="$(pwd)/bin;$PATH"
echo -e " ${YELLOW}Added: $(pwd)/bin${NC}"
fi
echo -e "${GREEN}Loaded Env${NC}"
}
#!/bin/bash
# Run the `php artisan` anywhere as long as you are within a repo with
# laravel installed.
RED='\033[0;31m'
GREEN='\033[1;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# Check to see if we are in a Git Repo
if git rev-parse --git-dir > /dev/null 2>&1; then
# This will open a terminal into the docker container app server.
REPO_DIR=$(git rev-parse --show-toplevel)
# Check that the composer.json exists
if [ ! -f "$REPO_DIR/composer.json" ]; then
echo -e "Can not find the ${RED}composer.json${NC}, can not ensure artisan will work."
exit 1
fi
php "${REPO_DIR}/artisan" $@
else
echo -e "${YELLOW}No Git Repo Found.${NC}"
echo -e "Can not locate the root of this project."
fi
#!/bin/bash
# Loads the "bin" folders for a command execution.
# This is helpful so you can be anywhere in the repo folder and be
# able to run a command without needing to back to the root or
# think about the realive path "../../vendor/bin/etcetc"
YELLOW='\033[1;33m'
RED='\033[0;31m'
NC='\033[0m' # No Color
if git rev-parse --git-dir > /dev/null 2>&1; then
# This will open a terminal into the docker container app server.
REPO_DIR=$(git rev-parse --show-toplevel)
NODE_PROJECT="${REPO_DIR}/node_modules/.bin"
if [ -d $NODE_PROJECT ]; then
echo -e "${YELLOW}Node Project${NC}"
PATH="$NODE_PROJECT:$PATH"
fi
COMPOSER_PROJECT="${REPO_DIR}/vendor/bin"
if [ -d $COMPOSER_PROJECT ]; then
echo -e "${YELLO}Composer Project${NC}"
PATH="$COMPOSER_PROJECT:$PATH"
fi
else
echo -e "${RED}No Repo Found. Nothing loaded.${NC}"
fi
# Execute all args as a command
$@
#!/bin/bash
# Clean Cahce in all app containers
RED='\033[0;31m'
GREEN='\033[1;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# Check to see if we are in a Git Repo
if git rev-parse --git-dir > /dev/null 2>&1; then
# This will open a terminal into the docker container app server.
REPO_DIR=$(git rev-parse --show-toplevel)
while IFS= read -r CONTAINER_NAME; do
# Is the container name NOT empty
if [ -n "$CONTAINER_NAME" ]; then
echo -e "Connecting to ${YELLOW}${CONTAINER_NAME}${NC}"
docker exec "${CONTAINER_NAME}" php artisan cache:clear
else
# Container Name is not found
echo -e "${RED}Container not found. Use \`app_server\` as the container name.\nFinally make sure the stack is running!${NC}"
fi
done <<<"$(docker ps --filter "label=com.docker.compose.project.working_dir=$REPO_DIR" --filter "status=running" --filter "name=app_server" --format '{{.Names}}')"
else
echo -e "${YELLOW}No Git Repo Found.${NC}"
echo -e "This will connect based on the git repo name."
echo -e "Verify that the ${RED}docker-compose${NC} stack is running!"
fi
#!/usr/bin/env python3
import sys
import os
import pandas as pd
import openpyxl
from openpyxl.utils.dataframe import dataframe_to_rows
# Converted using CSV to XLSX converter by OpenAI's ChatGPT.
# pip3 install openpyxl
# pip3 install pandas
def convert_csv_to_xlsx(csv_file, xlsx_file, sheet_name=None):
lock_file = f"~${os.path.basename(xlsx_file)}"
lock_file_path = os.path.join(os.path.dirname(xlsx_file), lock_file)
try:
print(f"CSV File: {csv_file}")
print(f"Excel File: {xlsx_file}")
print(f"Excel Lock: {lock_file}")
print(f"Sheet Name: {sheet_name}\n")
df = pd.read_csv(csv_file)
# create excel file
if os.path.isfile(xlsx_file): # if file already exists append to existing file
if os.path.exists(lock_file_path):
print("Error: The Excel file is currently open. Please close it and try again.")
return
workbook = openpyxl.load_workbook(xlsx_file) # load workbook if already exists
sheet = workbook[sheet_name] # declare the active sheet
# Clear the rows in the sheet
end_row = sheet.max_row
sheet.delete_rows(1, end_row + 1)
# Get the header as a list
header = df.columns.tolist()
# Insert the header as the first row
sheet.append(header)
# append the dataframe results to the current excel file
for row in dataframe_to_rows(df, header = False, index = False):
sheet.append(row)
workbook.save(xlsx_file) # save workbook
workbook.close() # close workbook
else: # create the excel file if doesn't already exist
with pd.ExcelWriter(path=xlsx_file, engine='openpyxl') as writer:
df.to_excel(writer, index=False, sheet_name=sheet_name)
print("Conversion completed successfully.")
except Exception as e:
exc_type, exc_obj, exc_tb = sys.exc_info()
fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
print(exc_type, fname, exc_tb.tb_lineno)
print(f"An error occurred: {e}")
# Check if the correct number of command-line arguments is provided
if len(sys.argv) < 4:
program_name = sys.argv[0]
print(f"Usage: {program_name} [data] [workbook] [sheet_name]")
print("\n[data]: Path to the input CSV file.")
print("[workbook]: Path to the output XLSX file.")
print("[sheet_name]: Name of the worksheet to replace in the XLSX file.")
else:
# Extract the command-line arguments
csv_file_path = sys.argv[1]
xlsx_file_path = sys.argv[2]
sheet_name = sys.argv[3]
convert_csv_to_xlsx(csv_file_path, xlsx_file_path, sheet_name)
# See the following link
# https://gist.github.com/nhalstead/2a2607043693ec140d8b07f71e7063e1
#!/bin/bash
# This will use `docker-machine` in order to run
# docker in a VM inside of XCP-NG Server.
# This takes in the IP, Username, Password, and VM Name
# This will install Porainer on the remote host to allow for a web
# admin page.
RED='\033[0;31m'
GREEN='\033[1;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
XCP_HOST=""
XCP_USERNAME=""
XCP_PASSWORD=""
XCP_VM_NAME=""
XCP_VM_IP=""
if [[ ! -x "$(command -v docker-machine)" ]]; then
echo "\`docker-machine\` is required. Please install the docker cli tools."
exit 1
fi
if [[ ! -x "$(command -v docker-machine-driver-xcp)" ]]; then
echo "\`docker-machine-driver-xcp\` is required. Please install the docker-machine driver for XCP."
echo -e "\thttps://github.com/interlegis/docker-machine-driver-xcp/releases"
exit 1
fi
if [[ ! -x "$(command -v jq)" ]]; then
echo "\`jq\` is required. Please install the jq. Try \`snap install yq\`"
exit 1
fi
if [[ ! -x "$(command -v curl)" ]]; then
echo "\`curl\` is required. Please install the curl."
exit 1
fi
if [ "$#" -eq 0 ] || [ "$#" -ne 4 ]; then
echo -e "Setup a new Docker Container in a Remote XCP-ng using 4 cores and 2 GB of RAM.\n"
echo -e "dockerxcp ${YELLOW}[host] [username] [password] [name]${NC}"
echo -e "\thost\t\tXCP-ng Host IP"
echo -e "\tusername\tXCP-ng Host Username"
echo -e "\tpassword\tXCP-ng Host Password"
echo -e "\tname\t\tXCP-ng VM name instance"
exit 1
fi
# Set Variables from CLI input
XCP_HOST="${1}"
XCP_USERNAME="${2}"
XCP_PASSWORD="${3}"
XCP_VM_NAME="${4}"
echo "Spawning docker vm with name ${XCP_VM_NAME} on XCPng Host ${XCP_HOST}."
# Run the deployment to XCP-NG using Docker Machine
echo -e "${YELLOW}\c"
docker-machine create -d xcp \
--xcp-server ${XCP_HOST} \
--xcp-username ${XCP_USERNAME} \
--xcp-password "${XCP_PASSWORD}" \
--xcp-vcpu-count 4 \
--xcp-memory-size 2048 \
"${XCP_VM_NAME}" \
| sed "s/^/ /"
echo -e "${NC}\n"
XCP_VM_IP="$(docker-machine ip "${XCP_VM_NAME}")"
##
## Installing 3rd Party Mgmt UI Portainer
##
read -p "Install Portainer? (y/n): "
if [[ $REPLY =~ ^[Yy]$ ]]; then
echo "Deploying Portainer"
# Deploy Portainer Volume
echo "Deploying Volume" | sed "s/^/ /"
echo -e "${GREEN}\c"
docker-machine ssh "${XCP_VM_NAME}" "docker volume create portainer_data" \
| sed "s/^/ /"
echo -e "${NC}"
# Deploy Portainer
echo "Deploying Container" | sed "s/^/ /"
echo -e "${GREEN}\c"
docker-machine ssh "${XCP_VM_NAME}" "docker run -d -p 8000:8000 -p 9000:9000 --name=portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer" \
| sed "s/^/ /"
echo -e "${NC}"
echo "Deployed Portainer to ${XCP_VM_NAME}"
echo "Portainer Version: $(curl -s "http://${XCP_VM_IP}:9000/api/status" | jq ".Version")"
echo -e "Web Interface \n http://${XCP_VM_IP}:9000/"
# Auto Configure User in Portainer
echo "Waiting for Portainer to start."
sleep 3
if [ "$(curl -s -o /dev/null -w "%{http_code}" "http://${XCP_VM_IP}:9000/api/users/admin/check")" -eq "404" ]; then
echo "Pending Admin Setup."
read -p "Automatic setup can be done here, do you wish to continue? (y/n): "
if [[ $REPLY =~ ^[Yy]$ ]]; then
# Setup Portainer User Account
read -ep " Username: " PORTAINER_USERNAME
read -esp " Password: " PORTAINER_PASSWORD
echo -e "\n"
# Create the Inital User
jq ".Username=\"${PORTAINER_USERNAME}\"" <<<"{}" \
| jq ".Password=\"${PORTAINER_PASSWORD}\"" \
| curl -s -d "$(</dev/stdin)" -H 'Content-Type: application/json' -X POST "http://${XCP_VM_IP}:9000/api/users/admin/init" > /dev/null
# Login as the New User, Parse for the JWT from the session.
TOKEN="$(echo "{}" \
| jq ".username=\"${PORTAINER_USERNAME}\"" \
| jq ".password=\"${PORTAINER_PASSWORD}\"" \
| curl -s -d "$(</dev/stdin)" -H 'Content-Type: application/json' -X POST "http://${XCP_VM_IP}:9000/api/auth" | jq ".jwt" --raw-output)"
read -p "Connect Portainer to localhost via Linux Socket? (y/n): "
if [[ $REPLY =~ ^[Yy]$ ]]; then
curl -s -X POST -H "Authorization: Bearer ${TOKEN}" -F "Name=local" -F "EndpointType=1" -F "URL=" \
-F "PublicURL=" -F "GroupID=1" -F "TagIds=[]" -F "TLS=false" "http://${XCP_VM_IP}:9000/api/endpoints" > /dev/null
fi
fi
else
echo "Portainer is not in a Provisioning State."
fi
fi
#!/bin/bash
# Export Common Packages using a TSV format
# Export globally installed packages from the following package managers
# dpkg/apt
# flatpack
# snap
# composer (PHP stuff)
# npm (NodeJS Stuff)
# yarn (NodeJS Stuff)
# brew (Mac and Linux Stuff)
# pip (Python Package Manager)
# krew (Kubctl Pligin Manager)
# sudo xargs -a completePackage.txt apt install
if [[ ! -x "$(command -v awk)" ]]; then
echo "\`awk\` is required. Please install \`awk\`."
exit 1;
fi
if [[ ! -x "$(command -v tail)" ]]; then
echo "\`tail\` is required. Please install \`tail\`."
exit 1;
fi
if [[ ! -x "$(command -v sed)" ]]; then
echo "\`sed\` is required. Please install \`sed\`."
exit 1;
fi
if [[ ! -x "$(command -v grep)" ]]; then
echo "\`grep\` is required. Please install \`grep\`."
exit 1;
fi
# Alias for Composer
# The executable can be composer or composer.phar
if [[ ! -x "$(command -v composer)" ]]; then
shopt -s expand_aliases
alias composer="$(which composer.phar)"
fi
# Is the first argugent NOT empty
if [ -n "$1" ]; then
# Call its self outputting the to the given file.
# $0 is the program's name, $1 is the file
$0 > $1
else
# Display the output to the user.
# dpkg --get-selections | sed -e "s/.*/deb \t&/"
if [[ -x "$(command -v apt-mark)" ]]; then
apt-mark showmanual \
| grep -v "linux-" \
| grep -v "language-pack" \
| grep -v "hunspell" \
| grep -v "hyphen" \
| grep -v "lib" \
| grep -v "gnome-" \
| grep -v "firefox-locale-" \
| grep -v "fonts-" \
| grep -v "system76-" \
| awk '{print $1}' \
| tail -n +1 \
| sed -e "s/.*/apt\t&/"
fi
if [[ -x "$(command -v flatpak)" ]]; then
flatpak list \
| sed -e "s/\s{2,}/\t&/" \
| grep -v "Application Platform" \
| awk 'BEGIN {FS="\t"}; {print $2}' \
| sed -e "s/.*/flatpack\t&/"
fi
if [[ -x "$(command -v snap)" ]]; then
snap list \
| grep -v "gnome-" \
| awk '{print $1}' \
| tail -n +2 \
| sed -e "s/.*/snap\t&/"
fi
if [[ -x "$(command -v composer)" ]]; then
composer global show 2>&1 \
| awk '{print $1}'\
| sed -e "s/.*/composer\t&/"
fi
if [[ -x "$(command -v npm)" ]]; then
npm list -g --depth 0 \
| awk '{print $2}' \
| tail -n +2 \
| sed -e '$ d' \
| sed -e "s/.*/npm\t&/"
fi
if [[ -x "$(command -v yarn)" ]]; then
yarn global list --depth 0 \
| awk '{print $2}' \
| tail -n +2 \
| sed -e '$ d' \
| sed -e "s/.*/yarn\t&/"
fi
if [[ -x "$(command -v brew)" ]]; then
brew list --formula --versions \
| sed -e "s/ \(.*\)$/ (\1)/" \
| sed -e "s/.*/brew\t&/"
fi
export PATH="${KREW_ROOT:-$HOME/.krew}/bin:$PATH"
if [[ -x "$(command -v kubectl)" ]] && kubectl krew > /dev/null; then
kubectl krew list \
| tail -n +1 \
| grep -v "krew" \
| sed -e "s/.*/krew \t&/"
fi
# Desn't check globally installed, needs sudo to do that.
if [[ -x "$(command -v pip)" ]]; then
pip list 2> /dev/null \
| tail -n +3 \
| awk '{print $1}' \
| sed -e "s/ {2,}/\t/g" \
| sed -e "s/.*/pip\t&/"
fi
if [ -d "/usr/local/bin" ]; then
# Scan the machine's common path
ls -AhFR /usr/local/bin \
| grep -v "/" \
| sed -e "s/@$//" \
| grep "*" \
| sed -e "s/\*//" \
| grep -v "\." \
| sed -e "s/.*/bin \t&/"
fi
fi
#!/bin/bash
# Runs the Laravel Artisan Command in the docker container.
# This is the same as the into command but prefixes it with the artisan command
# so it's a sub command of artisan.
# Is the first argugent NOT empty
if [ "$#" -ne 0 ]; then
# User Provided a artisan command
into "php artisan $@"
else
# Show general help messages
into "php artisan"
fi
#!/bin/bash
# Get a terminal into the docker container for this stack.
# This will connect to a docker container that has a name of `app_server`.
# To connect, it uses Git to get the current root path then uses docker
# ps and filters/labels to find the correct container to connect.
RED='\033[0;31m'
GREEN='\033[1;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# Default Terminal Enviornment, Bash or Sh
COMMAND="/bin/bash"
# Check to see if we are in a Git Repo
if git rev-parse --git-dir > /dev/null 2>&1; then
# This will open a terminal into the docker container app server.
REPO_DIR=$(git rev-parse --show-toplevel)
# Use Docker PS to get the matching containers then get the first container
CONTAINER_NAME=$(docker ps --filter "label=com.docker.compose.project.working_dir=$REPO_DIR" --filter "status=running" --filter "name=app_server" --format '{{.Names}}' | head -n 1)
# Is the container name NOT empty
if [ -n "$CONTAINER_NAME" ]; then
echo -e "Connecting to ${YELLOW}${CONTAINER_NAME}${NC}"
# Is the first argument NOT empty
if [ -n "$1" ]; then
echo -e "${GREEN}Running Custom Command${NC}"
# User Provided a Command to run.
COMMAND="${@}"
else
# Empty, Using the default Command
echo -e "Use ${GREEN}\`exit\`${NC} to leave the session."
fi
docker exec -it "${CONTAINER_NAME}" ${COMMAND}
else
# Container Name is not found
echo -e "${RED}Container not found. Use \`app_server\` as the container name.\nFinally make sure the stack is running!${NC}"
fi
else
echo -e "${YELLOW}No Git Repo Found.${NC}"
echo -e "This will connect based on the git repo name."
echo -e "Verify that the ${RED}docker-compose${NC} stack is running!"
fi
#!/bin/bash
# Uses kdump to create a nice ZIP Archive of the cluster's namespace.
# This will use the /tmp folder to make the downloads to then zips it
# and copies it to the current directory of execution.
# Once complete, it will remove the mess it has created.
#
# This command has a two odd commands that you may use.
# - (dash) This will export all namespaces into the Zip (see kdump)
# -each This will export each namespace into a Zip of thier own.
RED='\033[0;31m'
GREEN='\033[1;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
NAMESPACE="default"
if [ "$#" -eq 1 ] & [ "$1" == "--help" ]; then
echo -e "Export Deployments From Kubernetes Locally Selected Context then"
echo -e -n " zip all of the files\n"
echo -e "kbackup ${YELLOW}[namespace=default]${NC}"
echo -e "\tnamespace\tNamespace to export from."
exit 1
fi
if [ "$#" -eq 1 ]; then
# kdump [namespace]
NAMESPACE="${1}"
fi
if [[ ! -x "$(command -v kdump)" ]]; then
echo "\`kdump\` is required. Please add \`kdump\`."
exit 1;
fi
if [[ ! -x "$(command -v zip)" ]]; then
echo "\`zip\` is required. Try \`sudo apt install zip\`."
exit 1;
fi
if [[ ! -x "$(command -v kubectl)" ]]; then
echo "\`kubectl\` is required. Try \`brew install kubectl\`."
exit 1;
fi
# If searching for all namespaces
if [ "$1" == "-each" ]; then
# Get all namespaces and call this command again with each of the namespaces.
while IFS= read -r line; do
echo -e "Working in namespace: ${YELLOW}$line${NC}"
kbackup "$line"
done <<< "$(kubectl get namespace --no-headers -o custom-columns=":metadata.name")"
exit 0
fi
FILENAME="$(date "+%Y_%m_%d_%H_%M_%S")-$(kubectl config current-context)-${NAMESPACE}.zip"
tmp_dir=$(mktemp -d -t kbackup-XXXXXXXXXX)
# Change Diretories into the Tmp Dir to make a mess
# then package it into a nice zip, then clanup
pushd "${tmp_dir}" > /dev/null
kdump "${NAMESPACE}"
zip -r "${FILENAME}" *
popd > /dev/null
# Move the ZIP into the inital directoriy, remove
# the Temp Directory
mv "${tmp_dir}/${FILENAME}" "${FILENAME}"
rm -r "${tmp_dir}"
#!/bin/bash
# This script allows you to copy a currently running deployment in
# kubernetes and open a terminal in addition to a kubectl tunnel.
# The clone process will automatically adjust the labels as needed
# to ensure that the new deployment doesn't get included with the already\
# running deployment's service selectors.
# kdeployclone deploy_name new_name
RED='\033[0;31m'
GREEN='\033[1;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
DEPLOY_NAME=""
DEPLOY_CLONE_NAME=""
if [[ "$#" -eq 1 && "$1" == "--help" ]] || [ "$#" -eq 0 ] || [ "$#" -gt 2 ]; then
echo -e "Clone a currently running deployment and redeploy it."
echo -e " kdeployclone [deploy_name] [new_name={generate}]"
echo -e "\tname\tDeployment to export"
echo -e "\tnew_name\tNew Deployment name"
exit 1
fi
if [ "$#" -eq 2 ]; then
# kdeployclone [deploy_name] [new_name]
DEPLOY_NAME="${1}"
DEPLOY_CLONE_NAME="${2}"
else
# kdeployclone [deploy_name]
DEPLOY_NAME="${1}"
GIT_NAME=$(git config --global user.email | awk -F "@" '{print $1}')
EPOCH_TIME=$(date +%s)
DEPLOY_CLONE_NAME="${DEPLOY_NAME}-testing-${GIT_NAME}"
fi
OUTPUT_FILE="${DEPLOY_CLONE_NAME}.yaml"
OUTPUT_TEMP="${OUTPUT_FILE}.tmp"
# export deploy deploy_name
kexport deploy ${DEPLOY_NAME} > ${OUTPUT_FILE}
# reame deploy_name in YAML
cat ${OUTPUT_FILE} \
| yq w - "metadata.name" "${DEPLOY_CLONE_NAME}" \
| yq w - "metadata.labels.tier" "test" \
| yq w - "metadata.labels.cloned-from" "${DEPLOY_NAME}" \
| yq w - "spec.replicas" "1" \
| sed "s/run: ${DEPLOY_NAME}/run: ${DEPLOY_CLONE_NAME}/g" \
> ${OUTPUT_TEMP}
cat ${OUTPUT_TEMP} > ${OUTPUT_FILE}
rm ${OUTPUT_TEMP}
OPEN_PORT=$(cat ${OUTPUT_FILE} | yq r - "spec.template.spec.containers[0].ports[0].containerPort")
# deploy
kubectl apply -f ${OUTPUT_FILE}
trap "kubectl delete -f ${OUTPUT_FILE}" EXIT
# wait till deployed
kubectl wait --for=condition=available --timeout=600s deployment/${DEPLOY_CLONE_NAME}
echo "Deployment ${DEPLOY_CLONE_NAME} complete."
OPEN_PORT_PID=""
if [ "$OPEN_PORT" != "" ]; then
# Run port forward to the deployment to the local machine
kubectl port-forward deployment/${DEPLOY_CLONE_NAME} 3999:${OPEN_PORT} > /dev/null 2>&1 &
OPEN_PORT_PID=$!
echo -e "Port Forward from conatiner port ${GREEN}${OPEN_PORT}${NC} to ${YELLOW}3999${NC}"
fi
# Open an Shell into the deployment
kpodshell default ${DEPLOY_CLONE_NAME}
# Kill the port forward
if [ "$OPEN_PORT_PID" != "" ]; then
kill ${OPEN_PORT_PID}
echo -e "Killed the Port Forward process"
fi
#!/bin/bash
# Gets all Important Types of Resources in Kubernetes and exports them to the YAML
# files for recovery later.
# This will use kexport in order to omit fields that are not important for recovery.
RED='\033[0;31m'
GREEN='\033[1;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
NAMESPACE="default"
if [ "$#" -eq 1 ] & [ "$1" == "--help" ]; then
echo -e "Export Deployments From Kubernetes Locally Selected Context"
echo -e "kdump ${YELLOW}[namespace=default]${NC}"
echo -e "\tnamespace\tNamespace to export from."
exit 1
fi
if [ "$#" -eq 1 ]; then
# kdump [namespace]
NAMESPACE="${1}"
fi
if [[ ! -x "$(command -v kexport)" ]]; then
echo "\`kexport\` is required. Please add \`kexport\`."
exit 1;
fi
if [[ ! -x "$(command -v yq)" ]]; then
echo "\`yq\` is required. Please install \`yq\`. Try \`brew install yq\`"
exit 1;
fi
# Check YQ Version, Two variants of yq exists.
# Use the Golang based Version
# https://github.com/mikefarah/yq/
if [[ "$(yq -V)" != *"mikefarah/yq"* ]]; then
echo "Incorrect \`yq\` variant detected. Please install YQ from here https://github.com/mikefarah/yq/"
echo " or use brew \`brew install yq\`"
exit 1;
fi
# If searching for all namespaces
if [ "$1" == "-" ]; then
# Get all namespaces and call this command again with each of the namespaces.
while IFS= read -r line; do
echo -e "Working in namespace: ${YELLOW}$line${NC}"
kdump "$line"
done <<< "$(kubectl get namespace --no-headers -o custom-columns=":metadata.name")"
exit 0
fi
for n in $(kubectl get -n="$NAMESPACE" -o=name pvc,configmap,serviceaccount,secret,ingress,service,deployment,statefulset,hpa,job,cronjob)
do
RESOURCE_TYPE="$(echo $n | cut -d "/" -f 1)"
RESOURCE_NAME="$(echo $n | cut -d "/" -f 2)"
# Make path for type.
mkdir -p $(dirname $n)
echo -e -n "${YELLOW}${RESOURCE_NAME}${NC}...."
kexport "$RESOURCE_TYPE" "$NAMESPACE" "$RESOURCE_NAME" > $n.yaml
if [ "$RESOURCE_TYPE" == "service" ]; then
if [[ "$(yq '.metadata.ownerReferences[0].apiVersion' $n.yaml)" == "acme.cert-manager.io/v1" ]]; then
# Remove this file, its from a Cert Manager.
echo -e "${RED}Skipping${NC} Cert Manager Service for $(yq '.metadata.ownerReferences[0].name' $n.yaml)"
rm $n.yaml
continue
fi
fi
if [ "$RESOURCE_TYPE" == "job.batch" ]; then
if [ "$(yq '.metadata.ownerReferences[0].kind' $n.yaml)" == "CronJob" ]; then
# Remove this file, its from a CronJob Task.
# This is the instance of the scheduled cron job running.
echo -e "${RED}Skipping${NC} CronJob Pod for $(yq '.metadata.ownerReferences[0].name' $n.yaml)"
rm $n.yaml
continue
fi
fi
echo -e "${GREEN}Done${NC}"
done
#!/bin/bash
# Export the kube config for the given Kind and Name
# This will omit any cluster specific params and the output
# should be ready to pipe back into another creation without
# modification.
RED='\033[0;31m'
GREEN='\033[1;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
KIND_TAG=""
KIND_NAME=""
NAMESPACE=""
if [ "$#" -eq 0 ] || [ "$#" -gt 3 ] || [ "$1" == "--help" ]; then
echo -e "kexport ${YELLOW}[tag] [namespace=default] [name]${NC}"
echo -e "\ttag\tResource Type: deployment, secret, pod"
echo -e "\tnamespace\tNamespace, Deafult Value: default"
echo -e "\tname\tResource Name: prod-app"
exit 1
fi
if [[ ! -x "$(command -v yq)" ]]; then
echo "\`yq\` is required. Please install \`yq\`. Try \`snap install yq\`"
fi
# Check YQ Version, Two variants of yq exists.
# Use the Golang based Version
# https://github.com/mikefarah/yq/
if [[ "$(yq -V)" != *"mikefarah/yq"* ]]; then
echo "Incorrect \`yq\` variant detected. Please install YQ from here https://github.com/mikefarah/yq/"
echo " or use brew \`brew install yq\`"
exit 1;
fi
if [ "$#" -eq 3 ]; then
# kexport [tag] [namespace] [name]
KIND_TAG="${1}"
NAMESPACE="${2}"
KIND_NAME="${3}"
else
# kexport [tag] [name]
KIND_TAG="${1}"
KIND_NAME="${2}"
NAMESPACE="default"
fi
# Contact Kubernets Cluster to export the config
# then use `yq` to omit tags that are for this specific deployment
# link: https://stackoverflow.com/a/62230715/5779200
kubectl get $KIND_TAG "${KIND_NAME}" --namespace=$NAMESPACE -o yaml \
| yq e 'del(.metadata.managedFields)' - \
| yq e 'del(.metadata.resourceVersion)' - \
| yq e 'del(.metadata.uid)' - \
| yq e 'del(.metadata.annotations)' - \
| yq e 'del(.metadata.creationTimestamp)' - \
| yq e 'del(.metadata.selfLink)' - \
| yq e 'del(.metadata.generation)' - \
| yq e 'del(.status)' - \
| yq e 'del(.spec.template.metadata.creationTimestamp)' -
#!/bin/bash
set -eo pipefail
# Kubernetes Overview (ko)
# Simple Overview of the Kubernetes Pod running.
#
# This script uses the k8bit project to make this tie together.
# https://github.com/nhalstead/k8bit
if [[ ! -x "$(command -v python)" ]]; then
echo "\`kubectl\` is required. Try \`brew install kubectl\`."
exit 1;
fi
if [[ ! -x "$(command -v kubectl)" ]]; then
echo "\`kubectl\` is required. Try \`brew install kubectl\`."
exit 1;
fi
PORT="$(python -c 'import socket; s=socket.socket(); s.bind(("", 0)); print(s.getsockname()[1])')";
PROJECT_PATH="${GIT_PATH:-$HOME/GitHub}/k8bit"
# Check if the k8bit code exists
if [ ! -f $PROJECT_PATH ]; then
cd "${PROJECT_PATH}" || (
echo "Failed to switch to the project directory."
exit 1
)
open "http://localhost:${PORT}/static"
kubectl proxy --port="${PORT}" --www=. $@
else
echo "Failed to locate k8bit."
fi
#!/bin/bash
set -eo pipefail
# Open Pod Shell in the selected deployment
RED='\033[0;31m'
GREEN='\033[1;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
NAMESPACE="default"
DEPLOY_NAME=""
if [ "$#" -eq 2 ]; then
NAMESPACE="${1}"
DEPLOY_NAME="${2}"
else
echo "$0 [namespace] [deploy_name]"
exit 1
fi
# Get the Deployment selfLink value
LINK=$(kubectl get deployment.apps "${DEPLOY_NAME}" -n "${NAMESPACE}" -o jsonpath={.metadata.selfLink})
# Get the selector from by the Scale by selfLink
SELECTOR=$(kubectl get --raw "${LINK}/scale" | jq -r .status.selector)
# Get all matching pods and select the first entry
FIRST_POD=$(kubectl get pods -n "${ns}" --selector "${SELECTOR}" -o jsonpath={.items[*].metadata.name} | tr " " "\n" | head -n 1)
echo -e "Connecting to Pod ${YELLOW}${FIRST_POD}${NC}"
kubectl exec --stdin --tty ${FIRST_POD} -- /bin/bash
echo -e "Disconnected from Pod ${YELLOW}${FIRST_POD}${NC}"
#!/bin/bash
# Read the currently used resources in kubernetes
# This is used to read all API Resrouces related to this project
# in the kubernetes role out.
# All resources deployed to Kubernetes must contain the labels
# for this to work. Use labels `project` as the repo name and
# `tier` for "backend" or "frontend".
RED='\033[0;31m'
GREEN='\033[1;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
if [[ ! -x "$(command -v kubectl)" ]]; then
echo "\`kubectl\` is required. Please install the kubectl cli."
exit 1
fi
# Allow for a User to provide a project name.
# This checks if the first param is provided.
if [ -n "$1" ]; then
# User Provided project name to look under.
REPO_NAME="${1}"
else
# Empty, Using the auto detect method using the git repo name.
if [[ ! -x "$(command -v git)" ]]; then
echo "\`git\` is required. Please install the git cli."
exit 1
fi
if [[ ! -x "$(command -v basename)" ]]; then
echo "\`basename\` is required. Please install the basename cli."
exit 1
fi
# Check to see if we are in a Git Repo
if git rev-parse --git-dir > /dev/null 2>&1; then
# This will open a terminal into the docker container app server.
REPO_NAME=$(basename $(git rev-parse --show-toplevel))
else
echo -e "${YELLOW}No Git Repo Found.${NC}"
echo -e "This will lookup the project based on the git repo name."
echo -e "Verify that that kubernets is using the ${RED}project=\{repo_name\}${NC} label."
exit 1
fi
fi
echo -e "Kubernetes Resources for project ${YELLOW}${REPO_NAME}${NC}"
# If a kresource_color file is present use that
# for the output color effects.
if [ ! -f ~/bin/kresource_color ]; then
kubectl get all -l project=$REPO_NAME
else
kubectl get all -l project=$REPO_NAME | source kresource_color
fi
# Link: https://github.com/kubernetes/kubectl/issues/524#issuecomment-545377553
GREP_COLOR='01;32' egrep --color=always 'Running|$' | GREP_COLOR='01;33' egrep --color=always 'ContainerCreating|$' | GREP_COLOR='01;33' egrep --color=always 'Terminating|$' | GREP_COLOR='01;31' egrep --color=always 'Error|$' | GREP_COLOR='01;31' egrep --color=always 'CrashLoopBackOff|$' | GREP_COLOR='01;31' egrep --color=always 'ImagePullBackOff|$' | GREP_COLOR='01;33' egrep --color=always 'Pending|$'
#!/bin/bash
# Runs the Laravel Migration in the docker container.
# Is the first argugent NOT empty
if [ -n "$1" ]; then
# User Provided the flag to run a fresh clean database and run the
# the default DatabaseSeeder seeder.
if [ "$1" = "--fresh" ]; then
# Run a fresh migration
into "php artisan migrate:fresh --seed"
fi
else
# Run general DB Migration
into "php artisan migrate"
fi
#!/bin/bash
# Read the currently used resources in Docker
# All pods running in docker must contain the docker compose label
# for this to work. Use `docker compose up `and everything should show up.
RED='\033[0;31m'
GREEN='\033[1;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
if [[ ! -x "$(command -v docker)" ]]; then
echo "\`docker\` is required. Please install the docker cli."
exit 1
fi
# Allow for a User to provide a project directory.
# This checks if the first param is provided.
if [ -n "$1" ]; then
# User Provided project directory to look under.
REPO_DIR="${1}"
else
# Empty, Using the auto detect method using the git repo name.
if [[ ! -x "$(command -v git)" ]]; then
echo "\`git\` is required. Please install the git cli."
exit 1
fi
# Check to see if we are in a Git Repo
if git rev-parse --git-dir > /dev/null 2>&1; then
# This will open a terminal into the docker container app server.
REPO_DIR=$(git rev-parse --show-toplevel)
else
echo -e "${YELLOW}No Git Repo Found.${NC}"
echo -e "This will lookup the project based on the git repo name."
echo -e "Verify that that docker is using the ${RED}com.docker.compose.project.working_dir=\{repo_root\}${NC} label."
exit 1
fi
fi
echo -e "Local Docker Resources for project ${YELLOW}${REPO_DIR}${NC}"
# If a kresource_color file is present use that
# for the output color effects.
if [ ! -f ~/bin/kresource_color ]; then
docker ps --filter "label=com.docker.compose.project.working_dir=$REPO_DIR"
else
docker ps --filter "label=com.docker.compose.project.working_dir=$REPO_DIR" | source kresource_color
fi
#!/bin/bash
# Runs the Laravel Seeder that runs in the docker container.
# Is the first argugent NOT empty
if [ -n "$1" ]; then
# User Provided a seeder, Run that Class Seeder
into "php artisan db:seed --class=$1"
else
# Run general DB Seeder
into "php artisan db:seed"
fi
#!/bin/bash
# This will open a given path or default to open the current directory
xdg-open ${1:-$(pwd)}
#!/bin/bash
# Kill process by open port number
RED='\033[0;31m'
GREEN='\033[1;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
if [ "$#" -eq 0 ] || [ "$#" -gt 1 ]; then
echo -e "pokill ${YELLOW}[port]${NC}"
echo -e "\tport\tOpen Port to look for"
exit 1
fi
PID_OPENPORT="$(lsof -n -i4TCP:$1 | tail -n 1 | awk '{print $2}')"
if [ -n "$PID_OPENPORT" ]; then
# Port is open with a PID
PID_EXENAME="$(readlink /proc/$PID_OPENPORT/exe)"
read -p "Would you like to kill $PID_EXENAME? (y/n): "
if [[ $REPLY =~ ^[Yy]$ ]]; then
kill $PID_OPENPORT
fi
else
echo -e "${RED}Port is not open with a PID${NC}"
fi
#!/bin/bash
# Install Dependencies based on the project files.
# This will look at the different project file types for
# package managers and run the install process to setup
# said dependencies via the package managers.
# Supports:
# PHP Composer
# Node NPM
# Node Yarn
# Golang Go.Mod
# Java Maven
# Java Gradle
# Python Pip
# Python Pipenv
# Ruby Gem
RED='\033[0;31m'
GREEN='\033[1;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# If a composer config exists install
if [ -f composer.json ]; then
if [[ ! -x "$(command -v composer)" ]]; then
echo "\`composer\` is required. Please install the PHP Composer cli tool."
else
echo -e "Installing ${YELLOW}Composer${NC} Dependencies"
composer install
fi
fi
# If a Package config exists install
# BUT Detect if Yarn is being Used OR Npm.
if [ -f package.json ]; then
if [ -f yarn.lock ]; then
if [[ ! -x "$(command -v yarn)" ]]; then
echo "\`yarn\` is required. Please install Yarn cli tool."
else
echo -e "Installing ${YELLOW}Yarn${NC} Dependencies"
yarn install
fi
else
if [[ ! -x "$(command -v npm)" ]]; then
echo "\`npm\` is required. Please install Npm cli tool."
else
echo -e "Installing ${YELLOW}Npm${NC} Dependencies"
npm install
fi
fi
fi
# If a GO dependency config exists install
if [ -f go.mod ]; then
if [[ ! -x "$(command -v go)" ]]; then
echo "\`go\` is required. Please install the Go cli tool."
else
echo -e "Installing ${YELLOW}Go${NC} Dependencies"
go install
fi
fi
# If a Java Maven dependency config exists install
if [ -f pom.xml ]; then
if [[ ! -x "$(command -v mvn)" ]]; then
echo "\`mvn\` is required. Please install the Maven cli tool."
else
echo -e "Installing ${YELLOW}Maven${NC} Dependencies"
mvn install
fi
fi
# If a Java Gradle dependency config exists install
if [ -f build.gradle ]; then
if [[ ! -x "$(command -v gradlew)" ]]; then
echo "\`gradlew\` is required. Please install the Gradle cli tool."
else
echo -e "Running Build using ${YELLOW}Gradle${NC} to install Dependencies"
gradlew build
fi
fi
# If a python pip dependency config exists install
if [ -f requirements.txt ]; then
if [[ ! -x "$(command -v python)" ]]; then
echo "\`pip\` is required. Please install the pip cli tool."
else
echo -e "Installing ${YELLOW}Pip${NC} Dependencies"
pip install
fi
fi
# If a python pipenv dependency config exists install
if [ -f Pipfile ]; then
if [[ ! -x "$(command -v phpenv)" ]]; then
echo "\`phpenv\` is required. Please install the phpenv cli tool.\n \`pip install pipenv\`"
else
echo -e "Installing ${YELLOW}phpenv${NC} Dependencies"
phpenv install
fi
fi
# If a ruby gemfile dependency config exists install
if [ -f Gemfile ]; then
if [[ ! -x "$(command -v bundle)" ]]; then
echo "\`bundle\` is required. Please install the Ruby Bundle cli tool.\n \`gem install bundler\`"
else
echo -e "Installing ${YELLOW}Pip${NC} Dependencies"
bundle install
fi
fi
#!/bin/bash
# Clears the Docker Images that are not in use.
# https://forums.docker.com/t/how-to-delete-cache/5753
docker rmi $(docker images -a --filter=dangling=true -q)
#!/bin/bash
# Used to create a temporary folder to run a program.
RED='\033[0;31m'
GREEN='\033[1;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
if [ "$#" -eq 0 ] || [ "$1" == "--help" ]; then
echo -e "t ${YELLOW}[command...]${NC}"
exit 1
fi
BASH_T_COMMAND_DIR="$(mktemp -d -t "bash-t-command.XXXXXXX")"
BASH_T_COMMAND_DEST_DIR="$(pwd)"
pushd "${BASH_T_COMMAND_DIR}" > /dev/null
# Execute Commands
$@
cp -rv "$(pwd)/." "${BASH_T_COMMAND_DEST_DIR}"
popd > /dev/null
# Remove the temp folder
rm -rf "${BASH_T_COMMAND_DIR}"
#!/bin/bash
# Runs the Composer PHPUnit Test in the current repo.
# This means that you can be anywhere in within the Git repo
# and this will call the PHPUnit based on the root.
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# Check to see if we are in a Git Repo
if git rev-parse --git-dir > /dev/null 2>&1; then
REPO_DIRP=$(git rev-parse --show-toplevel)
cd "$REPO_DIRP" || exit
# Run general test with testdox flag.
./vendor/bin/phpunit --testdox
else
echo -e "${YELLOW}No Git Repo Found.${NC}"
echo -e "This will run phpunit based on the root of the git repo."
fi
#!/bin/bash
RED='\033[0;31m'
NC='\033[0m' # No Color
if [[ ! -x "$(command -v docker)" ]]; then
echo "\`docker\` is required."
exit 1
fi
echo -e "${GREEN}Updating Portainer${NC}"
# Pull the lastest Version
docker pull portainer/portainer-ce
# Stop the container
docker stop portainer
# Remove the container
docker rm portainer
# Re-deploy the portainer container
docker run -d -p 8000:8000 -p 9000:9000 --name=portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce
@nhalstead
Copy link
Author

These scripts are wrapped around the use of PHP with Laravel but can be repurposed to work with other frameworks or languages.

@nhalstead
Copy link
Author

nhalstead commented Sep 25, 2021

Need to update kdeployclone and kdump. The yq is different.

https://mikefarah.gitbook.io/yq/operators/assign-update

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment