Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add multiple placement options for multinode uniconfig deployment #244

Merged
merged 1 commit into from
Jan 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 11 additions & 12 deletions composefiles/swarm-uniconfig.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ x-logging: &logging_loki
- action: labelmap
regex: swarm_(service)

x-placement: &placement
placement:
constraints:
- node.role == manager
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should uniconfig be on manager node ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Default settings are for single-node deployment and all services are running on a master node.
This parameter is replaced during generation compose files by selected placement type.


services:
uniconfig:
image: traefik:v2.4
Expand Down Expand Up @@ -58,10 +63,8 @@ services:
hard: ${TF_ULIMIT_NPROC_HARD}
cap_drop:
- all
deploy:
placement:
constraints:
- node.id == ${UF_SWARM_NODE_ID}
deploy:
<<: *placement
mode: replicated
replicas: 1
resources:
Expand Down Expand Up @@ -133,10 +136,8 @@ services:
cap_add:
- CAP_NET_BIND_SERVICE
- NET_ADMIN
deploy:
placement:
constraints:
- node.id == ${UC_SWARM_NODE_ID}
deploy:
<<: *placement
restart_policy:
condition: any
delay: 5s
Expand Down Expand Up @@ -182,10 +183,8 @@ services:
cap_add:
- CAP_NET_BIND_SERVICE
- NET_ADMIN
deploy:
placement:
constraints:
- node.id == ${UC_SWARM_NODE_ID}
deploy:
<<: *placement
restart_policy:
condition: any
delay: 5s
Expand Down
134 changes: 118 additions & 16 deletions generate_uc_compose.sh
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,27 @@ OPTIONS:
-i|--instances [__UC_INSTANCES]
- Default : 2

-n|--node-id [SWARM-NODE-ID]
- Define swarm node id

-f|--folder-path [UNICONFIG FOLDER PATH]
- Define path, where will be
compose file stored.


SWARM NODE-PLACEMENT CONFIGURATION

--force [__FORCE_GENERATE]
- Allow re/generation of composefile with wrong parameters
- Default '${__FORCE_GENERATE}'

[USE ONLY ONE OPTION]

-n|--node-id [TYPE]
- Define services placement by node id
--hostname [TYPE]
- Define services placement by node hostname
--label [TYPE]
- Define services placement by node zone label
--role [TYPE]
- Define services placement by node role

COMMON SETTINGS

-h|--help Print this help and exit
Expand Down Expand Up @@ -57,20 +71,45 @@ do
if [[ ${2} != "-"* ]] && [[ ! -z ${2} ]]; then
checkUniconfigServiceName "${2}"
__SERVICE_NAME="${2}"
__SERVICE_NAME_DEFINED='true'
shift
else
echo "Service name not defined. See help!"
exit 1
fi;;

-n|--node-id)
if [[ ${2} != "-"* ]] && [[ ! -z ${2} ]]; then
__NODE_ID="${2}"; shift
-n|--node-id|--hostname|--label|--role)
if [ -z ${__only_one_config} ]; then
if [ ${1} == "-n" ]; then
__only_one_config="true"
TYPE="id"
elif [ ${1} == "--node-id" ]; then
__only_one_config="true"
TYPE="id"
elif [ ${1} == "--hostname" ]; then
__only_one_config="true"
TYPE="name"
elif [ ${1} == "--label" ]; then
__only_one_config="true"
TYPE="node.label"
elif [ ${1} == "--role" ]; then
__only_one_config="true"
TYPE="role"
fi

if [[ ${2} == '-'* ]] || [[ ${2} == '' ]] || [[ -z ${2} ]]; then
echo -e "${ERROR} Missing Swarm node placement input parameter for deployment: '${1}', type: 'node ${TYPE}'"
exit 1
else
__NODE_ID=${2}
shift
fi
else
echo "Service swarm node id not defined. See help!"
echo -e "${ERROR} Conflict parameters: -n|--node-id|--hostname|--label|--role !!! Just one can be selected !!!"
echo -e "Use '${scriptName} --help' for more details"
exit 1
fi;;

-i|--instances)
local regex='^[0-9]+$'
if [[ ${2} =~ ${regex} ]]; then
Expand All @@ -89,6 +128,10 @@ do
exit 1
fi;;

--force)
SWARM_STATUS=${WARNING}
__FORCE_GENERATE='true';;

-d|--debug)
set -x;;

Expand All @@ -98,6 +141,18 @@ do
esac
shift
done

if [[ -z $TYPE ]]; then
echo -e "${ERROR} Node placement type not defined. See help !!!"
exit 1
fi

if [[ -z $__SERVICE_NAME_DEFINED ]]; then
echo -e "${ERROR} Service name not defined. See help !!!"
exit 1
fi


}


Expand All @@ -115,10 +170,56 @@ function checkUniconfigServiceName {
}

function isNodeInSwarm {
if [[ "$(docker node ls -f id=${1} --format {{.ID}})" == "${1}" ]]; then
echo -e "${INFO} Node" ${1} "in swarm - Hostname: $(docker node ls -f id=${1} --format {{.Hostname}})"

bold=$(tput bold)
normal=$(tput sgr0)

node_hostname=$(docker node ls -f ${TYPE}=${1} --format {{.Hostname}}) ||
{ { echo -e "${ERROR} Bad node definition parameter ${bold}${TYPE}=${1}${normal}";} ;}

if [[ $node_hostname != '' ]] || [[ $__FORCE_GENERATE == 'true' ]] ; then

case $TYPE in
'id')
node=$(docker node inspect ${node_hostname} --format {{.ID}})
message="with ID"
deployment="node.id == ${1}"
;;

'name')
node=$(docker node inspect ${node_hostname} --format {{.Description.Hostname}})
message="with hostname"
deployment="node.hostname == ${1}"
;;

'node.label')
node=$(docker node inspect ${node_hostname} --format {{.Spec.Labels.zone}})
message="with label zone ="
deployment="node.labels.zone == ${1}"
;;

'role')
node=$(docker node inspect ${node_hostname} --format {{.Spec.Role}})
message="with role"
deployment="node.role == ${1}"
;;

*)
echo -e "${ERROR} ${TYPE} is not supported"
exit 1
;;
esac
fi

if [[ "${node}" == "${1}" ]]; then
echo -e "${INFO} Node ${message} ${bold}${1}${normal} is in swarm - Hostname: ${bold}${node_hostname}${normal}"
else
echo -e "${WARNING} Node ${1} not in swarm"
echo -e "${SWARM_STATUS} Node ${message} ${bold}${1}${normal} not in swarm"
if [[ $__FORCE_GENERATE == 'false' ]]; then
echo -e "${SWARM_STATUS} Composefiles was not generated"
exit 1
fi
echo -e "${SWARM_STATUS} Composefiles were force-generated with wrong placement settings"
fi
}

Expand Down Expand Up @@ -152,9 +253,8 @@ function generateUcCompose {
sed -i "s/ uniconfig-controller:/ ${__SERVICE_FULL_NAME}:/g" "${__COMPOSE_PATH}"
sed -i "s/ uniconfig-postgres:/ ${__SERVICE_NAME}-postgres:/g" "${__COMPOSE_PATH}"

# swarm node id
sed -i 's|${UC_SWARM_NODE_ID}|'"${__NODE_ID}|g" "${__COMPOSE_PATH}"
sed -i 's|${UF_SWARM_NODE_ID}|'"${__NODE_ID}|g" "${__COMPOSE_PATH}"
# swarm node deployment
sed -i "s/node.role == manager/${deployment}/g" "${__COMPOSE_PATH}"

# swarm config paths
sed -i 's|${UC_CONFIG_PATH}|'"/${__CONFIG_PATH}/${__UNICONFIG_SERVICE_SUFIX}|g" "${__COMPOSE_PATH}"
Expand Down Expand Up @@ -192,6 +292,7 @@ ERROR="\033[0;31m[ERROR]:\033[0;0m"
WARNING="\033[0;33m[WARNING]:\033[0;0m"
INFO="\033[0;96m[INFO]:\033[0;0m"
OK="\033[0;92m[OK]:\033[0;0m"
SWARM_STATUS=${ERROR}

FM_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
FM_COMPOSE_DIR="${FM_DIR}/composefiles"
Expand All @@ -203,10 +304,11 @@ __UC_COMPOSE_NAME="swarm-uniconfig.yml"

__DEF_CONFIG_PATH="opt/frinx"

__FORCE_GENERATE='false'
__UC_INSTANCES=2
__UNICONFIG_SERVICE_SUFIX="uniconfig-controller"

argumentsCheck "$@"
prepareFolder
isNodeInSwarm ${__NODE_ID}
prepareFolder
generateUcCompose
70 changes: 63 additions & 7 deletions startup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -185,16 +185,13 @@ function startUniconfig {
find ${uniconfigServiceFilesPath} -iname "swarm-uniconfig.yml" -print0 | \
while IFS= read -r -d '' compose_name; do
echo -e "${INFO} Checking swarm nodes for ${compose_name} uniconfig deployment"
node_id=($(grep node.id "${compose_name}" | sed -e 's/- node.id//;s/==//;s/^[[:space:]]*//'))
for node in "${node_id[@]}"
do
checkSwarmNodeActive "${node_id}"
done
node_id="$(grep node "${compose_name}" | sed -e 's/^[[:space:]]*//')"
checkUcSwarmMode "${node_id}"
docker stack deploy --compose-file ${compose_name} $stackName
done
else
echo -e "${INFO} Single-node deployment - composefiles/${dockerSwarmUniconfig}"
echo -e "${INFO} Uniconfig swarm worker node id: ${UC_SWARM_NODE_ID}"
echo -e "${INFO} Uniconfig swarm worker node hostname: ${UC_SWARM_NODE_ID}"
docker stack deploy --compose-file "composefiles/${dockerSwarmUniconfig}" $stackName
fi
}
Expand Down Expand Up @@ -278,6 +275,65 @@ function checkSwarmMode {
fi
}

function checkUcSwarmMode {

local TYPE="$(echo ${1}| cut -d ' ' -f 2)"
local PLACEMENT_INPUT="$(echo ${1}| cut -d ' ' -f 4)"
if [[ $PLACEMENT_INPUT != '' ]] && [[ $TYPE != '' ]] ; then

case $TYPE in
'node.id')
__id=$(docker node ls -f id=${PLACEMENT_INPUT} --format {{.ID}})
if [[ "${__id}" == "${PLACEMENT_INPUT}" ]];then
__name=$(docker node ls -f id=${PLACEMENT_INPUT} --format {{.Hostname}})
__status=$(docker node inspect ${__name} --format {{.Status.State}})
else
__name="node.id=${PLACEMENT_INPUT}"
__status='not found'
fi;;

'node.hostname')
__name=$(docker node ls -f name=${PLACEMENT_INPUT} --format {{.Hostname}})
if [[ "${__name}" == "${PLACEMENT_INPUT}" ]];then
__status=$(docker node inspect ${__name} --format {{.Status.State}})
else
__name="node.hostname=${PLACEMENT_INPUT}"
__status='not found'
fi;;

'node.labels.zone')
__name=$(docker node ls -f node.label=${PLACEMENT_INPUT} --format {{.Hostname}}) || true
if [[ "${__name}" != '' ]];then
__status=$(docker node inspect ${__name} --format {{.Status.State}})
else
__name="node.label=${PLACEMENT_INPUT}"
__status='not found'
fi;;

'node.role')
__name=$(docker node ls -f role=${PLACEMENT_INPUT} --format {{.Hostname}}) || true
if [[ "${__name}" != '' ]];then
__name=$(docker node ls -f role=${PLACEMENT_INPUT} --format {{.Hostname}})
__status=$(docker node inspect ${__name} --format {{.Status.State}})
else
__name="node.role=${PLACEMENT_INPUT}"
__status='not found'
fi;;
*)
echo -e "${ERROR} ${TYPE} is not supported"
return;;
esac

if [[ "${__status}" != "ready" ]]; then
echo -e "${ERROR} Swarm node: ${__name} - ${__node_id} ${__status:-not exist}"
elif [[ "${__status}" == "ready" ]]; then
echo -e "${OK} Swarm node ${__name} with placement type ${TYPE} = ${PLACEMENT_INPUT} is ${__status}"
fi
fi

}



function checkSwarmNodeActive {
local __node_id=${1}
Expand Down Expand Up @@ -428,7 +484,7 @@ performSettings="${productPerformSettingFile}"

# DEFAULT FM START SETTINGS
startupType="full"
nodeID=$(docker node ls --filter role=manager --format {{.ID}})
nodeID=$(docker node ls --filter role=manager --format {{.Hostname}})
export UC_CONFIG_PATH="${FM_DIR}/config/uniconfig/frinx/uniconfig"
export UF_CONFIG_PATH="${FM_DIR}/config"

Expand Down