#!/usr/bin/env sh
SERVICEMESH_ASM_VERSION='v1.2.5'
#!/bin/sh
# shellcheck disable=SC2039
VERBOSE=${VERBOSE:-3}
SERVICEMESH_VERSION=${SERVICEMESH_VERSION:-1.2.x}
SERVICEMESH_HELM_SUPPORTED_VERSIONS='^v3.(0|9)'
SUPPORTED_PROXY_PROTOCOLS='^(http|https)$'
SERVICEMESH_HELM_VERSION='v3.9.0'
SERVICEMESH_KUBE_VERSION='v1.21.0'
ACTIVATION_DATA=
SERVICEMESH_SUPPORTED_VERSIONS=
__ARGS="$@"
config_get_args() {
echo $__ARGS
}
config_set_args() {
__ARGS="$@"
}
config_get_activation_data () {
local PLATFORM_URI="$1"
local CLIENT_ID="$2"
local CLIENT_SECRET="$3"
local DATA
local REASON
local TOKEN
TOKEN=$(server_get_auth_token "$PLATFORM_URI" "$CLIENT_ID" "$CLIENT_SECRET")
if [ "$?" -ne "0" ]; then
# if an error occurs in server_get_auth_token it echoes the error message
REASON="$TOKEN"
echo "$REASON"
return 1
fi
DATA=$(server_get_activation_data "$PLATFORM_URI" "$TOKEN")
if [ "$?" -ne "0" ]; then
# if an error occurs in server_get_activation_data it echoes the error message
REASON="$DATA"
echo "$REASON"
return 1
fi
echo "$DATA"
}
config_set_activation_data () {
local DATA="$1"
ACTIVATION_DATA="$DATA"
}
config_get_supported_versions () {
local PLATFORM_URI="$1"
local SUPPORTED_VERSIONS
local REQUESTED_VERSION="$(version_get_number "$(config_get_asm_version)")"
[ -z "$REQUESTED_VERSION" ] && REQUESTED_VERSION="$(version_get_number "$(config_get_version)")"
SUPPORTED_VERSIONS=$(server_get_supported_versions "$PLATFORM_URI" "$REQUESTED_VERSION")
if [ "$?" -ne "0" ]; then
# if an error occurs in server_get_supported_versions it echoes the error message
REASON="$SUPPORTED_VERSIONS"
echo "$REASON"
return 1
fi
echo "$SUPPORTED_VERSIONS"
}
config_set_supported_versions () {
local SUPPORTED_VERSIONS="$1"
SERVICEMESH_SUPPORTED_VERSIONS="$SUPPORTED_VERSIONS"
}
config_get_kube_supported_versions () {
echo "$SERVICEMESH_SUPPORTED_VERSIONS" | jq -r '.k8s[]' | tr -d '\r' | tr '\n' ' '
}
config_get_istio_supported_versions () {
echo "$SERVICEMESH_SUPPORTED_VERSIONS" | jq -r '.istio[]' | tr -d '\r' | tr '\n' ' '
}
config_get_helm_supported_versions () {
echo "$SERVICEMESH_HELM_SUPPORTED_VERSIONS"
}
config_get_registry_hostname () {
echo "$ACTIVATION_DATA" | awk -F '=' '$1 == "registryHostname" { print $2; exit }'
}
config_get_master_organization_id () {
echo "$ACTIVATION_DATA" | awk -F '=' '$1 == "masterOrganizationId" { print $2; exit }'
}
config_get_proxy_uri () {
echo "${PROXY_PROTOCOL:+"${PROXY_PROTOCOL}://$PROXY_HOST:$PROXY_PORT"}"
}
config_get_proxy_user_pass () {
echo "${PROXY_USER:+"$PROXY_USER:$PROXY_PASSWORD"}"
}
config_get_version () {
echo "$SERVICEMESH_VERSION"
}
config_get_license () {
local LICENSE="$(license_digest "$LICENSE_PATH")"
echo "$LICENSE" | base64 | tr -d '\n\r'
}
config_get_option_platform_uri () {
SERVICEMESH_PLATFORM_URI=${SERVICEMESH_PLATFORM_URI:-https://anypoint.mulesoft.com}
# shellcheck disable=SC2046
utils_get_option --platformUri "$SERVICEMESH_PLATFORM_URI" $(config_get_args)
}
config_get_option_namespace () {
# shellcheck disable=SC2046
utils_get_option --namespace "$SERVICEMESH_NAMESPACE" $(config_get_args)
}
config_get_option_name () {
# shellcheck disable=SC2046
utils_get_option --name "" $(config_get_args)
}
config_get_option_client_id_or_prompt () {
# shellcheck disable=SC2046,SC2155
local RESULT="$(config_get_option_client_id)"
RESULT="${RESULT:-$(input_text "Please enter your Client Id")}"
echo "$RESULT"
}
config_get_option_client_id () {
# shellcheck disable=SC2046,SC2155
utils_get_option --clientId "$SERVICEMESH_CLIENT_ID" $(config_get_args)
}
config_get_option_client_secret_or_prompt () {
# shellcheck disable=SC2046,SC2155
local RESULT="$(config_get_option_client_secret)"
RESULT="${RESULT:-$(input_password "Please enter your Client Secret")}"
echo "$RESULT"
}
config_get_option_client_secret () {
# shellcheck disable=SC2046,SC2155
utils_get_option --clientSecret "$SERVICEMESH_CLIENT_SECRET" $(config_get_args)
}
config_get_option_proxy_protocol () {
# shellcheck disable=SC2046
utils_get_option --proxyProtocol "$PROXY_PROTOCOL" $(config_get_args)
}
config_get_option_proxy_host () {
# shellcheck disable=SC2046
utils_get_option --proxyHost "$PROXY_HOST" $(config_get_args)
}
config_get_option_proxy_port () {
# shellcheck disable=SC2046
utils_get_option --proxyPort "$PROXY_PORT" $(config_get_args)
}
config_get_option_proxy_user () {
# shellcheck disable=SC2046
utils_get_option --proxyUser "$PROXY_USER" $(config_get_args)
}
config_get_option_proxy_password () {
# shellcheck disable=SC2046
utils_get_option --proxyPassword "$PROXY_PASSWORD" $(config_get_args)
}
config_get_option_skip_resource_checks () {
# shellcheck disable=SC2046
utils_get_bool_option --skipResourceChecks "" $(config_get_args)
}
config_get_option_adapter_size () {
SERVICEMESH_ADAPTER_SIZE=${SERVICEMESH_ADAPTER_SIZE:-medium}
# shellcheck disable=SC2046
utils_get_option --size "$SERVICEMESH_ADAPTER_SIZE" $(config_get_args)
}
config_get_option_adapter_replicas () {
SERVICEMESH_ADAPTER_REPLICAS=${SERVICEMESH_ADAPTER_REPLICAS:-2}
# shellcheck disable=SC2046
utils_get_option --replicas "$SERVICEMESH_ADAPTER_REPLICAS" $(config_get_args)
}
config_get_option_service_name () {
# shellcheck disable=SC2046
utils_get_option --serviceName "$SERVICEMESH_SERVICE_NAME" $(config_get_args)
}
config_get_option_adapter_name () {
# shellcheck disable=SC2046
utils_get_option --adapter "$SERVICEMESH_ADAPTER_NAME" $(config_get_args)
}
config_get_option_api_id () {
# shellcheck disable=SC2046
utils_get_option --apiId "$SERVICEMESH_API_ID" $(config_get_args)
}
config_get_option_api_name () {
# shellcheck disable=SC2046
utils_get_option --api "$SERVICEMESH_API_NAME" $(config_get_args)
}
config_get_option_log4jfile () {
# shellcheck disable=SC2046
utils_get_option --log4jFile "" $(config_get_args)
}
config_get_option_license () {
# shellcheck disable=SC2046
utils_get_option --license "" $(config_get_args)
}
config_get_option_istio_namespace () {
# shellcheck disable=SC2046
utils_get_option --istioNamespace "istio-system" $(config_get_args)
}
config_get_option_mtls () {
SERVICEMESH_MTLS=${SERVICEMESH_MTLS:-disabled}
# shellcheck disable=SC2046
utils_get_option --mtls "$SERVICEMESH_MTLS" $(config_get_args)
}
config_get_option_flag_force () {
# shellcheck disable=SC2046
utils_get_bool_option -f "" $(config_get_args)
}
config_get_option_flag_all () {
# shellcheck disable=SC2046
utils_get_bool_option --all "" $(config_get_args)
}
config_get_option_flag_broker () {
# shellcheck disable=SC2046
utils_get_bool_option --broker "" $(config_get_args)
}
config_get_option_flag_brokerimpl () {
# shellcheck disable=SC2046
utils_get_bool_option --brokerImpl "" $(config_get_args)
}
config_get_option_flag_catalog () {
# shellcheck disable=SC2046
utils_get_bool_option --catalog "" $(config_get_args)
}
config_get_option_flag_istio () {
# shellcheck disable=SC2046
utils_get_bool_option --istio "" $(config_get_args)
}
config_get_helm_repo () {
local PLATFORM_URI="$1"
echo "${PLATFORM_URI}/servicemesh/xapi/v1/charts"
}
config_get_helm_version () {
echo "$SERVICEMESH_HELM_VERSION"
}
config_get_kube_version () {
echo "$SERVICEMESH_KUBE_VERSION"
}
config_get_helm_download_uri () {
local ARCH=""
local OS="$(utils_get_os)"
[ "$OS" = "Linux x86_64" ] && ARCH='linux-amd64'
[ "$OS" = "Darwin x86_64" ] && ARCH='darwin-amd64'
[ "$OS" = "Darwin arm64" ] && ARCH='darwin-arm64'
echo "https://get.helm.sh/helm-$(config_get_helm_version)-$ARCH.tar.gz"
}
config_get_kube_download_uri () {
local ARCH=""
local OS="$(utils_get_os)"
local VERSION="$(config_get_kube_version)"
[ "$OS" = "Linux x86_64" ] && ARCH='linux/amd64'
[ "$OS" = "Darwin x86_64" ] && ARCH='darwin/amd64'
[ "$OS" = "Darwin arm64" ] && ARCH='darwin/arm64'
echo "https://storage.googleapis.com/kubernetes-release/release/$VERSION/bin/$ARCH/kubectl"
}
config_get_asm_version () {
echo "${SERVICEMESH_ASM_VERSION:-unknown}"
}
config_get_asm_config_path () {
echo "$HOME/.asm"
}
config_get_asm_helm_path () {
echo "$(config_get_asm_config_path)/helm/$(config_get_helm_version)"
}
config_get_asm_kube_path () {
echo "$(config_get_asm_config_path)/kube/$(config_get_kube_version)"
}
config_get_asm_values_file_path () {
echo "$(config_get_asm_config_path)/values.yaml"
}
config_get_asm_logs_path () {
local SERVICEMESH_ASM_LOGS_PATH="$(config_get_asm_config_path)/logs"
[ ! -d "$SERVICEMESH_ASM_LOGS_PATH" ] && mkdir -p "$SERVICEMESH_ASM_LOGS_PATH"
echo "$SERVICEMESH_ASM_LOGS_PATH"
}
config_get_asm_log_file_path () {
SERVICEMESH_ASM_LOG_FILE_PATH=${SERVICEMESH_ASM_LOG_FILE_PATH:-"$(config_get_asm_logs_path)/asm.$(date -u +%Y%m%d).log"}
echo "$SERVICEMESH_ASM_LOG_FILE_PATH"
}
config_get_asm_temp_dump_folder () {
local DUMP_PATH="$(config_get_asm_config_path)/dump/$(date -u +%Y%m%d%H%M%S)"
[ ! -d "$DUMP_PATH" ] && mkdir -p "$DUMP_PATH"
echo "$DUMP_PATH"
}
#!/bin/sh
# shellcheck disable=SC2039,SC2155
# Determines if the user has necessary permissions to use the functions in this library to get resource usage in the cluster
cluster_resources_authorize () {
kube_check_permission "list" "nodes" \
&& kube_check_permission "get" "node" \
&& kube_check_permission "get" "lease" \
&& kube_check_permission "list" "pods" \
&& kube_check_permission "get" "pod" \
&& kube_check_permission "list" "events" \
&& kube_check_permission "get" "event"
}
# Checks if there are enough cluster resources to perform an action and if there are not, warns about it and prompts
# for consent and returns 0 if the user agrees, non-zero otherwise
cluster_resources_check_prompt () {
local message="$1"
local req_cpu="$2"
local req_mem="$3"
local missing_resources
if ! missing_resources="$(cluster_resources_check "$req_cpu" "$req_mem")"; then
local log_severity="$4" # will be used as the log function name
cluster_resources_prompt "$message" "$req_cpu" "$req_mem" "$missing_resources" "$log_severity" || return $?
fi
}
cluster_resources_prompt () {
local message="$1"
local req_cpu="$2"
local req_mem="$3"
local missing_resources="$4"
local log_severity="$5" # will be used as the log function name
if [ -z "$log_severity" ]; then
log_severity="warn"
fi
$log_severity "Currently there are scarce $missing_resources resources available in the cluster to $message."
$log_severity "This requires a total of ${req_cpu} CPU cores and ${req_mem} memory."
if [ "$log_severity" = "warn" ]; then
warn "The success of this action is not guaranteed, further resource management actions may be required."
fi
input_prompt_yes_no "Do you want to proceed?"
}
cluster_resources_check () {
local req_cpu="$1"
local req_mem="$2"
local cluster_resources="$(cluster_resources_get)"
local avail_nodes="$(echo "$cluster_resources" | awk '{ print $1 }')"
local avail_cpu="$(echo "$cluster_resources" | awk '{ print $2 }')"
local avail_mem="$(echo "$cluster_resources" | awk '{ print $3 }')"
local check_cpu="$(cluster_resources_normalize_cpu "$req_cpu")"
local check_mem="$(cluster_resources_normalize_mem "$req_mem")"
# if there is more than one node, check for a 15% more to give a margin for scheduling issues
if [ "$avail_nodes" -gt 1 ]; then
check_cpu=$((check_cpu * 115 / 100))
check_mem=$((check_mem * 115 / 100))
fi
local rem_cpu=$((avail_cpu - check_cpu))
local rem_mem=$((avail_mem - check_mem))
local missing_resources=""
if [ $rem_cpu -lt 0 ]; then
missing_resources="CPU"
fi
if [ $rem_mem -lt 0 ]; then
if [ -z "$missing_resources" ]; then
missing_resources="memory"
else
missing_resources="$missing_resources and memory"
fi
fi
echo "$missing_resources"
[ -z "$missing_resources" ] || return $?
}
# Returns the cluster resources in the format of "number_of_nodes total_cpu(millicores) total_memory(Ki)" (e.g. "2 3500 1048576")
cluster_resources_get () {
local total_cpu=0
local total_mem=0
local total_nodes=0
local names="$(kube_get_node_names)"
for name in $names
do
local resources="$(cluster_resources_get_node "$name")"
if [ "$resources" ]; then
local avail_cpu=$(echo "$resources" | awk '{ print $1 }')
local avail_mem=$(echo "$resources" | awk '{ print $2 }')
total_nodes=$((total_nodes + 1))
total_cpu=$((total_cpu + avail_cpu))
total_mem=$((total_mem + avail_mem))
fi
done
echo "${total_nodes} ${total_cpu} ${total_mem}"
}
# For a given node name, gets the available resources, or empty string if the node is not available for scheduling.
# Returns "cpu mem" (e.g. "3500 1048576")
cluster_resources_get_node() {
local name="$1"
local total_cpu total_mem
# create temp file to dump kubectl describe onto, to then repeatedly grep for details
local description_file="$(mktemp)"
kube_describe_node "$name" > "$description_file"
# check if its a 'tainted' node which won't count for the resources pool
if ! cluster_resources__is_tainted "$description_file"; then
# if its not tainted, check for available resources
local allocatable="$(cluster_resources__get_allocatable_resources "$description_file")"
local allocatable_cpu=$(echo "$allocatable" | awk '{ print $1 }')
local allocatable_mem=$(echo "$allocatable" | awk '{ print $2 }')
local allocated="$(cluster_resources__get_allocated_resources "$description_file")"
local allocated_cpu=$(echo "$allocated" | awk '{ print $1 }')
local allocated_mem=$(echo "$allocated" | awk '{ print $2 }')
rm -rf "$description_file"
total_cpu=$((allocatable_cpu - allocated_cpu))
total_mem=$((allocatable_mem - allocated_mem))
echo "$total_cpu $total_mem"
else
rm -rf "$description_file"
echo ""
fi
}
# Converts values like "2" to millicore values (e.g. "2048"). Leaves millicore values as is (i.e. 100m -> 100)
cluster_resources_normalize_cpu () {
local cpu="$1"
if echo "$cpu" | is_match "[0-9]+m"; then
echo "${cpu%m}" # strip the trailing 'm'
else
echo "$((cpu * 1024))"
fi
}
# Converts values like "2Mi" to Ki values (e.g. "2048"). Leaves Ki values as is (i.e. 100Ki -> 100). Considers Ki, Mi and Gi.
cluster_resources_normalize_mem () {
local mem="$1"
# if 1234Ki, just return the value 1234
echo "$mem" | is_match "[0-9]+Ki" && {
mem="${mem%Ki}" # strip the trailing Ki
}
# if 123Mi or 123Gi, return the equivalent in Ki without the unit
echo "$mem" | is_match "[0-9]+Mi" && {
mem="$((${mem%Mi} * 1024))"
}
echo "$mem" | is_match "[0-9]+Gi" && {
mem="$((${mem%Gi} * 1024 * 1024))"
}
echo "$mem"
}
#########################
# local utility functions
cluster_resources__get_allocatable_resources () {
cluster_resources__get_resources "Allocatable:" "System Info:" "$1"
}
cluster_resources__get_allocated_resources () {
cluster_resources__get_resources "Allocated resources:" "Events:" "$1"
}
# For a given string delimiters and a file with a kubectl describe node output, returns the resources "cpu memory"
cluster_resources__get_resources () {
local delim_start="$1"
local delim_end="$2"
local description_file="$3"
local cpu="$(awk "/$delim_start/,/$delim_end/" "$description_file" | awk '/cpu/ { print $2 }')"
local mem="$(awk "/$delim_start/,/$delim_end/" "$description_file" | awk '/memory/ { print $2 }')"
echo "$(cluster_resources_normalize_cpu "$cpu") $(cluster_resources_normalize_mem "$mem")"
}
cluster_resources__is_tainted () {
grep "Taints:" "$1" | is_match "NoSchedule|NoExecute"
}
events_track_event() {
local PLATFORM_URI="$1"
local PROPERTIES="$2";
local TYPE="$3";
local MASTER_ORGANIZATION_ID="$4";
local MASTER_ORGANIZATION_ID_FIELD
[ -z "$MASTER_ORGANIZATION_ID" ] || MASTER_ORGANIZATION_ID_FIELD="$(json_field_string "masterOrganizationId" "$MASTER_ORGANIZATION_ID")"
local URI="${PLATFORM_URI}/servicemesh/xapi/v1/events";
local PAYLOAD="$(json_object \
"$(json_field_string "type" "$TYPE")" \
"$(json_field "properties" "$PROPERTIES")" \
${MASTER_ORGANIZATION_ID_FIELD}
)"
local MAX_TIME_SECONDS="2";
curl -Ls \
-X POST \
-H "Content-Type: application/json" \
-m "$MAX_TIME_SECONDS" \
-d "$PAYLOAD" "$URI" >/dev/null 2>&1;
return 0;
}
#!/bin/sh
# shellcheck disable=SC2039,SC2015
openshift_is_present() {
kube_check_resource_exists_by_name 'crd/projects.config.openshift.io' 'none'
return $?
}
openshift_on_adapter_create_ok() {
local NAMESPACE="$1"
local NAME="$2"
debug "[openshift_on_adapter_create_ok] Called"
openshift_is_present || return 0
openshift_create_network_attachment_definition "$NAMESPACE" "istio-cni" || {
warn "Failed to create network-attachment-definition/istio-cni needed by Service Mesh Adapter '$NAME' in namespace '$NAMESPACE'"
}
return 0
}
openshift_create_network_attachment_definition() {
local NAMESPACE="$1"
local NAME="$2"
debug "[openshift_create_network_attachment_definition] Creating network-attachment-definition/$NAME in namespace '$NAMESPACE'"
{ cat << EOF
apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
name: ${NAME}
namespace: ${NAMESPACE}
EOF
} | kubectl apply -f - > /dev/null 2>&1 && {
debug "[openshift_create_network_attachment_definition] network-attachment-definition/$NAME in namespace '$NAMESPACE' created"
} || {
debug "[openshift_create_network_attachment_definition] Failed to create network-attachment-definition/$NAME in namespace '$NAMESPACE'"
return 1
}
}
#!/bin/sh
# shellcheck disable=SC2039
# Given a license file path, either already XML digest content or binary, output the XML digest of it
license_digest () {
local license_path="$1"
local license="$(cat "$license_path")"
echo "$license" | is_match "$(base64_file_encode "$license_path")"
}
echo "$license"
}
#!/bin/sh
_write() {
local severity="$1"; shift;
local title="$1"; shift;
local ASM_LOG_FILE="$(config_get_asm_log_file_path)"
echo "${severity}: ${title}\n $*\n" >> "$ASM_LOG_FILE"
}
file_debug() {
[ "$VERBOSE" -ge 4 ] && _write "DEBUG" "$@" || true
}
file_info() {
[ "$VERBOSE" -ge 3 ] && _write "INFO" "$@" || true
}
file_warn() {
[ "$VERBOSE" -ge 2 ] && _write "WARN" "$@" || true
}
file_error() {
[ "$VERBOSE" -ge 1 ] && _write "ERROR" "$@" || true
}
file_fatal() {
_write "FATAL" "$@" || true
exit 1
}
#!/bin/sh
# shellcheck disable=SC2039
## kubernetes commands
kubectl () {
local KUBE_BIN="$(config_get_asm_kube_path)/kubectl"
debug "[kubectl] $*"
kube_download && "$KUBE_BIN" "$@"
}
kube_get_version () {
kubectl version --short | awk '/Server/{print $3}'
}
kube_get_client_version () {
kubectl version --client --short | awk '/Client/{print $3}'
}
kube_check_version () {
local VERSIONS="$(config_get_kube_supported_versions)"
local KUBE_VERSION="$(version_get_number "$(kube_get_version)")"
local IS_MATCH=1
for v in $VERSIONS
do
if echo "$KUBE_VERSION" | grep -q "$v"; then
IS_MATCH=0
fi
done
return $IS_MATCH
}
kube_check_permission () {
[ "$#" -lt 2 ] && fatal "kube_check_permission() missing args"
local OPE="$1"
local RESOURCE="$2"
local NAMESPACE="${3:+-n $3}"
NAMESPACE="${NAMESPACE:---all-namespaces}"
kubectl auth can-i "$OPE" "$RESOURCE" "$NAMESPACE" > /dev/null && return 0 || return $?
}
# Test to see if any resources exist in the 'all' category using the specified label.
# stdout: None
# Return code: 0 if exists
kube_check_resource_exists_by_label() {
[ "$#" -eq 0 ] && fatal "kube_check_resource_exists_by_label() missing args"
local LABEL="$1"
local NAMESPACE="${2:+-n $2}"
NAMESPACE="${NAMESPACE:---all-namespaces}"
# Fail if no output.
debug "[kube_check_resource_exists_by_label] LABEL=$LABEL NAMESPACE=$NAMESPACE"
[ "$(kubectl get all -l "$LABEL" -ogo-template='{{.items|len}}' "$NAMESPACE")" = "0" ] && return 1 || return 0
}
# Test to see if any resources exist using the canonical name.
# stdout: None
# Return code: 0 if exists
kube_check_resource_exists_by_name() {
[ "$#" != 2 ] && fatal "kube_check_resource_exists_by_name() missing args"
local NAME="$1"
local NAMESPACE="$2"
# Fail if no stdout
debug "[kube_check_resource_exists_by_name] NAME=$NAME NAMESPACE=$NAMESPACE"
[ "$(kubectl -n "$NAMESPACE" get "$NAME" -oname --ignore-not-found)" ] && return 0 || return 1
}
kube_check_resource_exists_by_name_accross_namespaces() {
local NAME="$1"
local RESOURCE="$2"
debug "[kube_check_resource_exists_by_name_accross_namespaces] NAME=$NAME RESOURCE=$RESOURCE"
[ -z "$(kubectl get "$RESOURCE" -oname --all-namespaces | awk /$NAME/)" ] && return 1 || return 0
}
kube_check_no_resource_exists_across_namespaces() {
[ "$#" != 1 ] && fatal "kube_check_no_resource_exists_across_namespaces() missing args"
local RESOURCE="$1"
debug "[kube_check_no_resource_exists_across_namespaces] RESOURCE=$RESOURCE"
[ "$(kubectl get "$RESOURCE" --all-namespaces -ogo-template='{{.items|len}}')" = "0" ] && return 0 || return 1
}
kube_check_condition() {
[ "$#" != 3 ] && fatal "kube_check_condition() missing args"
local NAME="$1"
local CONDITION="$2"
local NAMESPACE="$3"
# Fail if no stdout
debug "[kube_check_condition] NAME=$NAME CONDITION=$CONDITION NAMESPACE=$NAMESPACE"
kubectl -n "$NAMESPACE" wait "$NAME" "--for=condition=$CONDITION" > /dev/null && return 0 || return $?
}
kube_create_namespace () {
[ "$#" != 1 ] && fatal "kube_create_namespace() missing args"
local NAMESPACE="$1"
kubectl create namespace "$NAMESPACE" --dry-run -oyaml | kubectl apply -f - > /dev/null && return 0 || return $?
}
kube_create_serviceaccount () {
[ "$#" != 2 ] && fatal "kube_create_serviceaccount() missing args"
local NAME="$1"
local NAMESPACE="$2"
debug "[kube_create_serviceaccount] NAME=$NAME NAMESPACE=$NAMESPACE"
kubectl -n "$NAMESPACE" create serviceaccount "$NAME" --dry-run -oyaml | kubectl apply -f - > /dev/null && return 0 || return $?
}
kube_create_clusterrolebinding () {
[ "$#" != 3 ] && fatal "kube_create_clusterrolebinding() missing args"
local NAME="$1"
local CLUSTERROLE="$2"
local SA="$3"
debug "[kube_create_clusterrolebinding] NAME=$NAME CLUSTERROLE=$CLUSTERROLE SERVICEACCOUNT=$SA"
kubectl create clusterrolebinding "$NAME" "--clusterrole=$CLUSTERROLE" "--serviceaccount=$SA" --dry-run -oyaml | kubectl apply -f - > /dev/null && return 0 || return $?
}
kube_create_secret () {
[ "$#" != 4 ] && fatal "kube_create_secret() missing args"
local NAME="$1"
local NAMESPACE="$2"
local KEY="$3"
local VALUE="$4"
kubectl -n "$NAMESPACE" create secret generic "$NAME" "--from-literal=$KEY=$VALUE" --dry-run -oyaml | kubectl apply -f - > /dev/null && return 0 || return $?
}
kube_add_label () {
[ "$#" -lt 4 ] && fatal "kube_add_label() missing args"
local RESOURCE="$1"
local NAME="$2"
local LABELNAME="$3"
local LABELVALUE="$4"
local NAMESPACE="${5:-default}"
debug "[kube_add_label] NAMESPACE=$NAMESPACE RESOURCE=$RESOURCE NAME=$NAME LABEL=$LABELNAME=$LABELVALUE"
kubectl -n "$NAMESPACE" label --overwrite "$RESOURCE" "$NAME" "$LABELNAME=$LABELVALUE" > /dev/null && return 0 || return $?
}
kube_remove_label () {
[ "$#" -lt 3 ] && fatal "kube_remove_label() missing args"
local RESOURCE="$1"
local NAME="$2"
local LABELNAME="$3"
local NAMESPACE="${4:-default}"
debug "[kube_remove_label] NAMESPACE=$NAMESPACE RESOURCE=$RESOURCE NAME=$NAME LABELNAME=$LABELNAME"
kubectl -n "$NAMESPACE" label "$RESOURCE" "$NAME" "${LABELNAME}-" > /dev/null && return 0 || return $?
}
kube_delete () {
[ "$#" != 3 ] && fatal "kube_delete() missing args"
local RESOURCE="$1"
local NAME="$2"
local NAMESPACE="$3"
debug "[kube_delete] RESOURCE=$RESOURCE NAME=$NAME NAMESPACE=$NAMESPACE"
kubectl -n "$NAMESPACE" delete --ignore-not-found "$RESOURCE" "$NAME" > /dev/null && return 0 || return $?
}
kube_delete_all () {
[ "$#" != 3 ] && fatal "kube_delete_all() missing args"
local RESOURCE="$1"
local NAME="$2"
local NAMESPACE="$3"
debug "[kube_delete_all] RESOURCE=$RESOURCE NAME=$NAME NAMESPACE=$NAMESPACE"
kubectl -n "$NAMESPACE" delete $(kubectl -n "$NAMESPACE" get "$RESOURCE" -oname | awk "/$NAME/") > /dev/null && return 0 || return $?
}
kube_download () {
local KUBE_URI="$(config_get_kube_download_uri)"
local KUBE_PATH="$(config_get_asm_kube_path)"
local KUBE_BIN="$KUBE_PATH/kubectl"
local FEATURES_ERROR_MSG
[ ! -f "$KUBE_BIN" ] && {
info "Downloading Kubectl..."
debug "[kube_download] Downloading from $KUBE_URI to $KUBE_BIN"
FEATURES_ERROR_MSG="$(features curl)"
if [ "$?" -ne "0" ]; then
rm -rf "$KUBE_PATH"
error "$FEATURES_ERROR_MSG"
fatal "Downloading Kubectl from $KUBE_URI"
fi
mkdir -p "$KUBE_PATH" && \
curl -fLs -o "$KUBE_BIN" "$KUBE_URI" && \
chmod +x "$KUBE_BIN" && {
info "Kubectl downloaded"
return 0
} || {
rm -rf "$KUBE_PATH"
fatal "Downloading Kubectl from $KUBE_URI"
}
}
return 0
}
kube_write_licence_failure_log () {
local ERR_MSG=$(kubectl -n service-mesh get pod -l "job-name=service-mesh-license-validator" -o go-template="{{range .items}}{{range .status.containerStatuses}}{{.state.terminated.message}}{{end}}{{end}}")
file_error "License Validation" "$ERR_MSG"
}
kube_get_resource_fields () {
local NAME="$1"
local NAMESPACE="$2"
local FIELDS="$3"
kubectl get "$NAME" -n "$NAMESPACE" -o jsonpath="$FIELDS"
}
kube_patch_resource_keys () {
local NAME="$1"
local NAMESPACE="$2"
local OPS="$3"
kubectl patch "$NAME" -n "$NAMESPACE" --type=json -p="[ $OPS ]" > /dev/null && return 0 || return $?
}
kube_get_node_names () {
kubectl get node -oname
}
kube_describe_node () {
local RESOURCE="$1"
kubectl describe "$RESOURCE"
}
kube_apply_dry_run () {
kubectl apply --dry-run "$@"
}
#!/bin/sh
# shellcheck disable=SC2039,SC2155
# --- servicemesh commands ---
servicemesh_get_platform_uri() {
local RESULT
servicemesh_is_installed && {
RESULT="$(helm get values service-mesh -n service-mesh -oyaml | awk '/platformUri/{print $2}')"
}
RESULT="${RESULT:-$(config_get_option_platform_uri)}"
echo "$RESULT"
}
servicemesh_get_client_id() {
local RESULT="$(config_get_option_client_id)"
servicemesh_is_installed && {
RESULT="${RESULT:-$(helm get values service-mesh -n service-mesh -oyaml | awk '/clientId/{print $2}')}"
}
echo "$RESULT"
}
servicemesh_get_client_secret() {
local RESULT="$(config_get_option_client_secret)"
servicemesh_is_installed && {
RESULT="${RESULT:-$(helm get values service-mesh -n service-mesh -oyaml | awk '/clientSecret/{print $2}')}"
}
echo "$RESULT"
}
servicemesh_get_version() {
local RESULT
servicemesh_is_installed && {
RESULT="$(helm_chart_version service-mesh-uber service-mesh)"
}
RESULT="${RESULT:-$(config_get_version)}"
echo "$RESULT"
}
servicemesh_is_installed () {
helm_chart_is_installed 'service-mesh' 'service-mesh' && return 0 || return $?
}
servicemesh_svccat_is_installed () {
local CMD
CMD="$(kubectl get crd --selector="svcat=true" -o=jsonpath="{.items[0].spec.names.categories}" 2>/dev/null)"
if [ "$?" -ne "0" ]; then
return 1
fi
echo "$CMD" | grep "all" > /dev/null 2>&1 && return 0 || return $?
}
servicemesh_get_adapter_proxy () {
local PROXY_PARAMS
if [ -n "$PROXY_PROTOCOL" ]
then
PROXY_PARAMS="--set=service-mesh-incluster-service-broker-implementation.proxy.$PROXY_PROTOCOL.host=$PROXY_HOST --set=service-mesh-incluster-service-broker-implementation.proxy.$PROXY_PROTOCOL.port=$PROXY_PORT --set=service-mesh-incluster-service-broker-implementation.proxy.$PROXY_PROTOCOL.user=$PROXY_USER --set=service-mesh-incluster-service-broker-implementation.proxy.$PROXY_PROTOCOL.pass=$PROXY_PASSWORD"
PROXY_PARAMS="$PROXY_PARAMS --set=service-mesh-incluster-service-broker-implementation.proxy.platform.host=$PROXY_HOST --set=service-mesh-incluster-service-broker-implementation.proxy.platform.port=$PROXY_PORT --set=service-mesh-incluster-service-broker-implementation.proxy.platform.user=$PROXY_USER --set=service-mesh-incluster-service-broker-implementation.proxy.platform.pass=$PROXY_PASSWORD"
fi
echo "$PROXY_PARAMS"
}
servicemesh_is_mtls_enabled () {
[ "$(config_get_option_mtls)" = "enabled" ] && echo "true" || echo "false"
}
servicemesh_additional_helm_args () {
local PLATFORM_URI="$1"
local REGISTRY_HOSTNAME="$(config_get_registry_hostname)"
local MULE_LICENSE="$(config_get_license)"
local ROTATOR_PROXY_URI="$(config_get_proxy_uri)"
local ROTATOR_PROXY_USER_PASS="$(config_get_proxy_user_pass)"
local IMPL_PROXY_PARAMS="$(servicemesh_get_adapter_proxy)"
local MTLS_ENABLED="$(servicemesh_is_mtls_enabled)"
echo "--set=global.image.registry=${REGISTRY_HOSTNAME}" \
"--set=global.imagePullSecrets={service-mesh-pull-secret}" \
"--set=global.anypoint.platformUri=${PLATFORM_URI}" \
"--set=global.anypoint.clientId=$(config_get_option_client_id)" \
"--set=global.anypoint.clientSecret=$(config_get_option_client_secret)" \
"--set=global.anypoint.license='${MULE_LICENSE}'" \
"--set=registry-credentials-rotator.proxy.uri=${ROTATOR_PROXY_URI}" \
"--set=registry-credentials-rotator.proxy.user=${ROTATOR_PROXY_USER_PASS}" \
"--set=registry-credentials-rotator.rotator.secretName=service-mesh-pull-secret" \
"--set=registry-credentials-rotator.rotator.secretNamespace=service-mesh" \
"$IMPL_PROXY_PARAMS" \
"--set=service-mesh-incluster-service-broker-implementation.mtls.enabled=${MTLS_ENABLED}" \
"--set=service-mesh-incluster-service-broker-implementation.license='${MULE_LICENSE}'"
}
servicemesh_check_install_resources () {
local PLATFORM_URI="$1"
local HELM_REPO="$(config_get_helm_repo "$PLATFORM_URI")"
local VERSION="$(config_get_version)"
local HELM_ARGS="$(servicemesh_additional_helm_args "$PLATFORM_URI")"
local RESOURCES
RESOURCES="$(helm_calc_chart_resources "$HELM_REPO" "service-mesh-uber" "$VERSION" "$HELM_ARGS")" || {
input_prompt_yes_no "Unable to determine resource requirements. Proceed with installation?"
return $?
}
local INSTALL_CPU="$(echo "$RESOURCES" | awk '{print $1}')"
local INSTALL_MEM="$(echo "$RESOURCES" | awk '{print $2}')"
local MISSING_RESOURCES;
if MISSING_RESOURCES="$(cluster_resources_check "${INSTALL_CPU}m" "${INSTALL_MEM}Ki")"; then
# available resources for installation, check-prompt if enough for installation + small adapter
local ADAPTER_SIZE="small"
local ADAPTER_REPLICAS="1"
local ADAPTER_CPU="$(cluster_resources_normalize_cpu "$(adapter_get_cpu_request $ADAPTER_SIZE $ADAPTER_REPLICAS)")"
local ADAPTER_MEM="$(cluster_resources_normalize_mem "$(adapter_get_mem_request $ADAPTER_SIZE $ADAPTER_REPLICAS)")"
INSTALL_CPU=$((INSTALL_CPU + ADAPTER_CPU))
INSTALL_MEM=$((INSTALL_MEM + ADAPTER_MEM))
# check for available resources for installing ASM + creating the smallest possible adapter, if not enough, notify
# in info level not warning about potential failure of the current action
cluster_resources_check_prompt \
"create a $ADAPTER_SIZE adapter with $ADAPTER_REPLICAS replica after completing the installation" \
"${INSTALL_CPU}m" "${INSTALL_MEM}Ki" "info"
else
# not enough resources for install, prompt
cluster_resources_prompt "install Anypoint Service Mesh" "${INSTALL_CPU}m" "${INSTALL_MEM}Ki" "$MISSING_RESOURCES"
fi
}
servicemesh_install_chart () {
local PLATFORM_URI="$1"
local REGISTRY_HOSTNAME="$(config_get_registry_hostname)"
local VERSION="$(config_get_version)"
local HELM_ARGS="$(servicemesh_additional_helm_args "$PLATFORM_URI")"
debug "[servicemesh_install_chart] REGISTRY_HOSTNAME=$REGISTRY_HOSTNAME PLATFORM_URI=$PLATFORM_URI VERSION=$VERSION"
# HELM_ARGS should not be quoted so that arguments reach the helm command individually
# shellcheck disable=SC2086
logger_mute run_and_log helm upgrade --install --atomic --namespace service-mesh "--version=${VERSION}" --timeout 20m0s \
service-mesh service-mesh/service-mesh-uber \
$HELM_ARGS \
&& return 0 || return $?
}
servicemesh_uninstall_chart () {
run_and_log helm uninstall --namespace=service-mesh service-mesh > /dev/null && sleep 30 && return 0 || return $?
}
servicemesh_config_chart () {
local PLATFORM_URI="$1"
local VERSION="$2"
local CLIENT_ID="$3"
local CLIENT_SECRET="$4"
local MTLS_ENABLED="$5"
local VALUES_PATH="$(config_get_asm_values_file_path)"
# save user supplied values in a temporary file and delete it at function call end
helm get values service-mesh -n service-mesh -oyaml > "$VALUES_PATH"
trap "rm -f ${VALUES_PATH}" RETURN
debug "[servicemesh_config_chart] PLATFORM_URI=$PLATFORM_URI VERSION=$VERSION CLIENT_ID=${CLIENT_ID} MTLS_ENABLED=${MTLS_ENABLED}"
helm upgrade \
--atomic \
--namespace service-mesh \
--timeout 10m0s \
"--version=${VERSION}" \
"--values=$VALUES_PATH" \
"--set=global.anypoint.clientId=${CLIENT_ID}" \
"--set=global.anypoint.clientSecret=${CLIENT_SECRET}" \
"--set=service-mesh-incluster-service-broker-implementation.mtls.enabled=${MTLS_ENABLED}" \
service-mesh service-mesh/service-mesh-uber > /dev/null \
&& return 0 || return $?
}
servicemesh_upgrade_chart () {
local VERSION="$(config_get_version)"
local VALUES_PATH="$(config_get_asm_values_file_path)"
local SERVICEMESH_VERSION="$(helm_chart_version service-mesh-uber service-mesh)"
# save user supplied values in a temporary file and delete it at function call end
helm get values service-mesh -n service-mesh -oyaml > "$VALUES_PATH"
trap "rm -f ${VALUES_PATH}" RETURN
debug "[servicemesh_upgrade_chart] VERSION=$VERSION"
helm upgrade --atomic --namespace service-mesh "--version=${VERSION}" --timeout 10m0s --values "$VALUES_PATH" "--set=upgrade.previousVersion=${SERVICEMESH_VERSION}" service-mesh service-mesh/service-mesh-uber > /dev/null \
&& return 0 || return $?
}
servicemesh_install () {
local PLATFORM_URI="$1"
info "Install Service Mesh..."
info "> Add Service Mesh Helm Repository..."
helm_repo_add 'service-mesh' "$(config_get_helm_repo "$PLATFORM_URI")" || {
echo "Adding Service Mesh Helm Repository!!!"
return 1
}
if [ "$(config_get_option_skip_resource_checks)" ]; then
info "> Skipping available cluster resources checks..."
else
## check enough available cluster resources for installing (and minimally using)
info "> Checking available cluster resources..."
servicemesh_check_install_resources "$PLATFORM_URI" || {
echo "> Cancelled due to insufficient cluster resources"
return 1
}
fi
servicemesh_svccat_is_installed && {
echo "> Service Catalog already installed, if you previously installed it on this cluster, please uninstall it first!!!"
return 1
}
info "> Install 'service-mesh' Helm Chart..."
servicemesh_install_chart "$PLATFORM_URI" || {
local PRE_INSTALL_ERROR_MESSAGE="$(servicemesh_check_pre_install_errors)"
echo "${PRE_INSTALL_ERROR_MESSAGE:-"Installing 'service-mesh' Helm Chart!!!"}"
return 1
}
return $?
}
servicemesh_uninstall () {
info "Uninstall Service Mesh..."
info "> Remove 'service-mesh' Helm Chart..."
servicemesh_is_installed && {
servicemesh_uninstall_chart || {
fatal "Removing 'service-mesh' Helm Chart!!!"
}
} || {
warn "'service-mesh' Helm Chart isn't installed"
return 0
}
return $?
}
servicemesh_upgrade () {
local PLATFORM_URI="$1"
info "Upgrade Service Mesh..."
servicemesh_is_installed || {
echo "> Service Mesh is not installed"
return 1
}
info "> Updating Service Mesh Helm Repository..."
helm_repo_add 'service-mesh' "$(config_get_helm_repo "$PLATFORM_URI")" || {
echo "Updating Service Mesh Helm Repository!!!"
return 1
}
info "> Upgrade 'service-mesh' Helm Chart..."
servicemesh_upgrade_chart || {
echo "Upgrading 'service-mesh' Helm Chart!!!"
return 1
}
return $?
}
servicemesh_config () {
local PLATFORM_URI="$(servicemesh_get_platform_uri)"
local VERSION="$(servicemesh_get_version)"
local CLIENT_ID="$(servicemesh_get_client_id)"
local CLIENT_SECRET="$(servicemesh_get_client_secret)"
local MTLS_ENABLED="$(servicemesh_is_mtls_enabled)"
info "Config Service Mesh..."
servicemesh_is_installed || {
echo "> Service Mesh is not installed"
return 1
}
info "> Updating Service Mesh Helm Repository..."
helm_repo_add 'service-mesh' "$(config_get_helm_repo "$PLATFORM_URI")" || {
echo "Updating Service Mesh Helm Repository!!!"
return 1
}
info "> Config 'service-mesh' Helm Chart..."
servicemesh_config_chart "$PLATFORM_URI" "$VERSION" "$CLIENT_ID" "$CLIENT_SECRET" "$MTLS_ENABLED" || {
echo "Configuring 'service-mesh' Helm Chart!!!"
return 1
}
return $?
}
servicemesh_check_pre_install_errors () {
#If licence validator job exists after failure it means licence is not valid
kube_check_resource_exists_by_name "job.batch/service-mesh-license-validator" "service-mesh" > /dev/null 2>&1 && {
local JOB_ERROR=$(kubectl -n service-mesh get job.batch/service-mesh-license-validator -ogo-template="{{range .status.conditions}}{{.reason}}{{end}}")
if [ "$JOB_ERROR" = "DeadlineExceeded" ]; then
kube_check_resource_exists_by_label "job-name=service-mesh-license-validator" "service-mesh" || {
echo "There was an error pulling license validation image, please try again."
return 1
}
echo "There was an error running license validation job, please try again."
return 1
elif [ "$JOB_ERROR" = "BackoffLimitExceeded" ]; then
kube_write_licence_failure_log
echo "Provided License is not valid. Check logs at $(config_get_asm_log_file_path)"
return 1
fi
}
}
#!/bin/sh
# shellcheck disable=SC2039
istio_get_version () {
local namespace="$1"
kubectl get pods -n "$namespace" -l istio --field-selector status.phase=Running -o jsonpath='{.items[].spec.containers[].image}' 2> /dev/null | awk -F: '{ print $2 }' && return 0 || return $?
}
istio_check_version () {
local namespace="$1"
local versions="$(config_get_istio_supported_versions)"
local istio_version="$(istio_get_version "$namespace")"
local is_match=1
for v in $versions
do
if echo "$istio_version" | grep -q "$v"; then
is_match=0
fi
done
return $is_match
}
#!/bin/sh
# shellcheck disable=SC2039,SC2155
## helm helper functions
helm () {
local HELM_BIN="$(config_get_asm_helm_path)/helm"
debug "[helm] $*"
helm_download && "$HELM_BIN" "$@"
}
helm_get_client_version () {
helm version --short 2> /dev/null && return 0 || return $?
}
helm_check_client_version () {
local VERSIONS="$(config_get_helm_supported_versions)"
helm_get_client_version | is_match "$VERSIONS" && return 0 || return $?
}
helm_chart_is_installed () {
[ "$#" -lt 1 ] && fatal "helm_chart_is_installed(name, [namespace]) missing args"
local NAME="$1"
local NAMESPACE="${2:-kube-system}"
helm --namespace "$NAMESPACE" status "$NAME" > /dev/null 2>&1 && return 0 || return $?
}
helm_chart_version () {
[ "$#" -lt 1 ] && fatal "helm_chart_version(name, [namespace]) missing args"
local NAME="$1"
local NAMESPACE="${2:-kube-system}"
helm --namespace "$NAMESPACE" ls | awk "/$NAME/{gsub(\"$NAME-\",\"\",\$9);print \$9}" 2>&1 && return 0 || return $?
}
helm_repo_add () {
[ "$#" != 2 ] && fatal "helm_repo_add(name, repo) missing args"
local NAME="$1"
local REPO="$2"
helm repo add "$NAME" "$REPO" > /dev/null 2>&1 && helm repo up > /dev/null 2>&1 && return 0 || return $?
}
helm_download () {
local HELM_URI="$(config_get_helm_download_uri)"
local HELM_PATH="$(config_get_asm_helm_path)"
local OUT_FILE="$HELM_PATH/out.tgz"
local FEATURES_ERROR_MSG
[ ! -d "$HELM_PATH" ] && {
info "Downloading Helm"
debug "[helm_download] Downloading from $HELM_URI to $HELM_PATH"
FEATURES_ERROR_MSG="$(features curl tar)"
if [ "$?" -ne "0" ]; then
rm -rf "$HELM_PATH"
error "$FEATURES_ERROR_MSG"
fatal "Downloading Helm from $HELM_URI"
fi
mkdir -p "$HELM_PATH" && \
curl -fLs -o "$OUT_FILE" "$HELM_URI" && \
tar -xzC "$HELM_PATH" --strip-components=1 -f "$HELM_PATH/out.tgz" && {
info "Helm downloaded"
return 0
} || {
rm -rf "$HELM_PATH"
fatal "Downloading Helm from $HELM_URI"
}
}
return 0
}
helm_template () {
local HELM_REPO="$1"
local CHART_NAME="$2"
local VERSION="$3"
local HELM_ARGS="$4"
# shellcheck disable=SC2086
helm template --repo "$HELM_REPO" "$CHART_NAME" --version="${VERSION}" $HELM_ARGS
}
# Given a helm charts repository, chart name, chart version and optional additional arguments, calculates and returns
# the requested "cpu mem" in millicores and Ki (e.g. "250 303104") by all the deployments in the chart
helm_calc_chart_resources () {
local HELM_REPO="$1"
local CHART_NAME="$2"
local VERSION="$3"
local HELM_ARGS="$4"
local GO_TEMPLATE="
{{- range .items}}
{{- if eq .kind \"Deployment\"}}
{{- if .spec.replicas }}{{.spec.replicas}}{{else}}1{{end}}{{\"\t\"}}
{{- range .spec.template.spec.containers}}
{{- if .resources.requests.cpu }}{{.resources.requests.cpu}}{{else}}0m{{end}}/{{if .resources.requests.memory }}{{.resources.requests.memory}}{{else}}0Ki{{end}},
{{- end}}
{{- \":\"}}
{{- end}}
{{- end}}
"
local CHARTS
CHARTS="$(helm_template "$HELM_REPO" "$CHART_NAME" "$VERSION" "$HELM_ARGS")" || return $?
local DEPLOYMENTS="$(helm_filter_resource_kind "$CHARTS" Deployment)"
local RESOURCES_DATA
RESOURCES_DATA="$(echo "$DEPLOYMENTS" | kube_apply_dry_run -o go-template="$GO_TEMPLATE" -f -)" || return $?
local INSTALL_CPU="0"
local INSTALL_MEM="0"
local IFS_BACKUP="$IFS"
IFS=":"
for i in $RESOURCES_DATA; do
local replicas="$(echo "$i" | awk '{print $1}')"
local containers_cpu="0"
local containers_mem="0"
local containers_resources="$(echo "$i" | awk '{print $2}' | tr "," ":")"
for j in $containers_resources; do
local container_cpu="$(echo "$j" | awk -F "/" '{print $1}')"
container_cpu="$(cluster_resources_normalize_cpu "$container_cpu")"
local container_mem="$(echo "$j" | awk -F "/" '{print $2}')"
container_mem="$(cluster_resources_normalize_mem "$container_mem")"
containers_cpu="$((containers_cpu + container_cpu))"
containers_mem="$((containers_mem + container_mem))"
done
INSTALL_CPU=$((INSTALL_CPU + replicas * containers_cpu))
INSTALL_MEM=$((INSTALL_MEM + replicas * containers_mem))
done
IFS="$IFS_BACKUP"
echo "$INSTALL_CPU $INSTALL_MEM"
}
helm_filter_resource_kind() {
local RESOURCES="$1"
local KIND="$2";
local FILTERED=""
local CURRENT=""
local MATCH=0
local IFS_BACKUP="$IFS"
local IFS='
'
for line in $RESOURCES; do
CURRENT="${CURRENT:+$CURRENT$IFS}$line"
case "$line" in
"kind: ${KIND}")
MATCH=1;;
kind:*)
MATCH=0;;
---)
if [ $MATCH -eq 1 ]; then
FILTERED="${FILTERED:+$FILTERED$IFS}$CURRENT"
fi
CURRENT=""
MATCH=0;;
esac
done
if [ $MATCH -eq 1 ]; then
FILTERED="${FILTERED:+$FILTERED$IFS}$CURRENT"
fi
IFS="$IFS_BACKUP"
echo "$FILTERED"
}
#!/bin/sh
# shellcheck disable=SC2039
join_by () {
local IFS="$1"
shift
echo "$*"
}
json_string () {
printf '"%s"' "$1"
}
json_number () {
echo "$1"
}
json_bool () {
case "$1" in
false|no|0) echo "false" ;;
*) echo "true" ;;
esac
}
json_null () {
echo "null"
}
json_object () {
printf '{%s}' "$(join_by "," "${@}")"
}
json_array () {
printf '[%s]' "$(join_by "," "${@}")"
}
json_field () {
printf '"%s":%s' "$1" "$2"
}
json_field_string () {
json_field "$1" "$(json_string "$2")"
}
json_field_number () {
json_field "$1" "$(json_number "$2")"
}
json_field_bool () {
json_field "$1" "$(json_bool "$2")"
}
json_field_null () {
json_field "$1" "$(json_null)"
}
json_field_object () {
local NAME="$1"; shift
json_field "$NAME" "$(json_object "${@}")"
}
json_field_array () {
local NAME="$1"; shift
json_field "$NAME" "$(json_array "${@}")"
}
#!/bin/sh
## get base64 representation of string content
base64_encode () {
local CONTENT="$1"
echo "$CONTENT" | base64 | tr -d '\n\r'
}
## get base64 representation of file content
base64_file_encode () {
local FILEPATH="$1"
cat "$FILEPATH" | base64 | tr -d '\n\r'
}
#!/bin/sh
server_get_auth_token() {
assert_equal "$#" "3" "get_auth_token() missing args"
local PLATFORM_URI="$1"
local CLIENT_ID="$2"
local CLIENT_SECRET="$3"
[ -n "$(config_get_proxy_uri)" ] && local CURL_PROXY="-x $(config_get_proxy_uri)"
[ -n "$(config_get_proxy_user_pass)" ] && local CURL_PROXY_USER="--proxy-user $(config_get_proxy_user_pass)"
local RESPONSE_FILE=$(mktemp)
debug "curl -Ls -X POST ${CURL_PROXY} ${CURL_PROXY_USER} -H \"Content-Type: application/json\" -d \"{\"client_id\":\"$CLIENT_ID\",\"client_secret\":\"$CLIENT_SECRET\",\"grant_type\":\"client_credentials\"}\" \"${PLATFORM_URI}/accounts/oauth2/token\""
local STATUS=$(curl -Ls -X POST ${CURL_PROXY} ${CURL_PROXY_USER} -H "Content-Type: application/json" -w "%{http_code}" -d "{\"client_id\":\"$CLIENT_ID\",\"client_secret\":\"$CLIENT_SECRET\",\"grant_type\":\"client_credentials\"}" -o "$RESPONSE_FILE" "${PLATFORM_URI}/accounts/oauth2/token")
trap "rm -rf $RESPONSE_FILE" EXIT
debug "[server_get_auth_token] CLIENT_ID=$CLIENT_ID STATUS=$STATUS"
if [ "$STATUS" -eq "200" ]; then
cat "$RESPONSE_FILE" | awk 'BEGIN{FS=":";RS=","} {gsub(/[\"\}\{\n]/, "", $0)} /access_token/{print $2}'
return 0
elif [ "$STATUS" -eq "401" ]; then
echo "The given credentials are invalid"
return 1
else
echo "An unexpected error occurred while getting token from Anypoint Platform"
return 1
fi
}
server_get_activation_data() {
assert_equal "$#" "2" "get_activation_data() missing args"
local PLATFORM_URI="$1"
local TOKEN="$2"
[ -n "$(config_get_proxy_uri)" ] && local CURL_PROXY="-x $(config_get_proxy_uri)"
[ -n "$(config_get_proxy_user_pass)" ] && local CURL_PROXY_USER="--proxy-user $(config_get_proxy_user_pass)"
local RESPONSE_FILE=$(mktemp)
debug "curl -Ls -X GET ${CURL_PROXY} ${CURL_PROXY_USER} -H \"Accept: text/plain\" -H \"Authorization: Bearer ${TOKEN}\" \"${PLATFORM_URI}/servicemesh/xapi/v1/config/activation\""
local STATUS=$(curl -Ls -X GET ${CURL_PROXY} ${CURL_PROXY_USER} -H "Accept: text/plain" -H "Authorization: Bearer ${TOKEN}" -w "%{http_code}" -o "$RESPONSE_FILE" "${PLATFORM_URI}/servicemesh/xapi/v1/config/activation")
trap "rm -rf $RESPONSE_FILE" EXIT
debug "[server_get_activation_data] TOKEN=$TOKEN STATUS=$STATUS"
if [ "$STATUS" -eq "200" ]; then
cat "$RESPONSE_FILE"
return 0
elif [ "$STATUS" -eq "403" ]; then
echo "The given credentials does not have the necessary permissions or entitlements"
return 1
else
echo "An unexpected error occurred while getting activation data from Anypoint Platform"
return 1
fi
}
server_get_supported_versions() {
assert_equal "$#" "2" "get_supported_versions() missing args"
local PLATFORM_URI="$1"
local VERSION="$2"
[ -n "$(config_get_proxy_uri)" ] && local CURL_PROXY="-x $(config_get_proxy_uri)"
[ -n "$(config_get_proxy_user_pass)" ] && local CURL_PROXY_USER="--proxy-user $(config_get_proxy_user_pass)"
local RESPONSE_FILE=$(mktemp)
debug "curl -s -X GET ${CURL_PROXY} ${CURL_PROXY_USER} \"${PLATFORM_URI}/servicemesh/xapi/v1/install/supported-versions?version=${VERSION}\""
local STATUS=$(curl -s -X GET ${CURL_PROXY} ${CURL_PROXY_USER} -w "%{http_code}" -o "$RESPONSE_FILE" "${PLATFORM_URI}/servicemesh/xapi/v1/install/supported-versions?version=${VERSION}")
trap "rm -rf $RESPONSE_FILE" EXIT
debug "[server_get_supported_versions] STATUS=$STATUS"
if [ "$STATUS" -eq "200" ]; then
cat "$RESPONSE_FILE"
return 0
elif [ "$STATUS" -eq "400" ]; then
echo "The install version is invalid or does not exist"
return 1
else
echo "An unexpected error occurred while getting the supported versions from Anypoint Platform for this version"
return 1
fi
}
#!/bin/sh
# shellcheck disable=SC2039
# Prompts the user the specified message followed by a [y/n] input
input_prompt_yes_no () {
local MESSAGE="$1"
input_text "$MESSAGE [y/n]" | is_match '^[Yy]$'
}
# Let the user enter a variable.
# Optionally specify a default value.
input_text () {
local MESSAGE="$1"
local VAR=""
if [ $# -eq 2 ]; then
DEFAULT="$2"
printf "> %s [%s]: " "${MESSAGE}" "${DEFAULT}" 1>&2
read -r VAR
if [ -z "${VAR}" ]; then
VAR="${DEFAULT}"
fi
else
printf "> %s: " "${MESSAGE}" 1>&2
read -r VAR
fi
echo "${VAR}"
}
input_path () {
input_text "$@" | awk -v HOME="$HOME" "{gsub(/~/, HOME); print}"
}
# Let the user enter a hidden variable (e.g., password).
input_password () {
stty -echo
trap 'stty echo' EXIT
input_text "$@"
stty echo
trap - EXIT
echo 1>&2
}
#!/bin/sh
# shellcheck disable=SC2039
# --- asserts functions ---
assert_not_empty () {
local VALUE="$1"
local MSG="${2:-VALUE can not be empty}"
[ -z "$VALUE" ] && fatal "$MSG" || return 0
}
assert_empty () {
local VALUE="$1"
local MSG="${2:-VALUE should be empty}"
[ -n "$VALUE" ] && fatal "$MSG" || return 0
}
assert_equal () {
local ACTUAL="$1"
local EXPECTED="$2"
local MSG="${3:-VALUE should be '$EXPECTED' but was '$ACTUAL'}"
[ "$ACTUAL" = "$EXPECTED" ] && return 0 || fatal "$MSG"
}
assert_not_equal () {
local ACTUAL="$1"
local EXPECTED="$2"
local MSG="${3:-VALUE '$EXPECTED' and '$ACTUAL' should not be equals}"
[ "$ACTUAL" != "$EXPECTED" ] && return 0 || fatal "$MSG"
}
assert_file_exists () {
local VALUE="$1"
local MSG="${2:-'$VALUE' file not found}"
[ ! -f "$VALUE" ] && fatal "$MSG" || return 0
}
assert_pattern () {
local PATTERN="$1"
local VALUE="$2"
local MSG="${3:-'$VALUE' not match pattern $PATTERN}"
echo "$VALUE" | awk "/$PATTERN/{RC=0}BEGIN{RC=1}END{exit RC}" && return 0 || fatal "$MSG"
}
assert_servicemesh_is_installed () {
local MSG="${1:-Service Mesh not installed in this cluster!!!}"
kube_check_resource_exists_by_name ns/service-mesh all || fatal "$MSG"
}
assert_kube_server_version () {
local SUPPORTED_VERSIONS="$(config_get_kube_supported_versions)"
local VERSION="$(kube_get_version)"
local IS_MATCH=1
local MSG="${1:-Service Mesh need kubernetes version ~ [ $SUPPORTED_VERSIONS ] to be installed!!!}"
for v in $SUPPORTED_VERSIONS
do
if echo "$VERSION" | grep -q "$v"; then
IS_MATCH=0
fi
done
assert_equal "$IS_MATCH" "0" "$MSG"
}
assert_kube_resource_exists () {
local RESOURCE="$1"
local NAMESPACE="$2"
local MSG="${3:-Resource '$RESOURCE' should exists}"
kube_check_resource_exists_by_name "$RESOURCE" "$NAMESPACE" || fatal "$MSG"
}
assert_kube_resource_not_exists () {
local RESOURCE="$1"
local NAMESPACE="$2"
local MSG="${3:-Resource '$RESOURCE' should not exists}"
kube_check_resource_exists_by_name "$RESOURCE" "$NAMESPACE" && fatal "$MSG"
}
assert_kube_namespace_exists () {
local NAMESPACE="$1"
local MSG="${2:-Namespace '$NAMESPACE' should exists}"
assert_not_empty "$NAMESPACE" "Namespace should be defined!!!"
assert_kube_resource_name "$NAMESPACE"
assert_kube_resource_exists "namespace/$NAMESPACE" all "$MSG"
}
assert_kube_resource_name () {
local VALUE="$1"
local PATTERN='^[a-z0-9]([-a-z0-9]*[a-z0-9])?$'
local MSG="${2:-'$VALUE' has invalid format, it should consist of lower case alphanumeric characters or '-', and must start and end with an alphanumeric character (e.g. 'my-name', or '123-abc', regex used for validation is '$PATTERN')}"
assert_pattern "$PATTERN" "$VALUE" "$MSG"
}
assert_platform_uri () {
local VALUE="$1"
local MSG="${2:-'$VALUE' is an invalid Anypoint Platform Uri}"
assert_not_empty "$VALUE" "Anypoint Platform URI can't be empty"
assert_pattern '^http(s)?\:\/\/' "$VALUE" "Anypoint Platform URI should start with http(s)://"
curl -XOPTIONS -sSf "$1/servicemesh/xapi/v1/install" > /dev/null 2>&1 || fatal "$MSG"
}
assert_adapter_replicas () {
local VALUE="$1"
assert_not_empty "$VALUE" "Adapter replicas can't be empty"
assert_pattern '^[1-8]$' "$VALUE" "Adapter replicas should be a number [1..8]"
}
assert_adapter_exists () {
local NAMESPACE="$1"
local NAME="$2"
assert_not_empty "$NAME" "Adapter name should be defined!!!"
assert_kube_resource_name "$NAME"
assert_not_empty "$NAMESPACE" "Namespace should be defined!!!"
assert_kube_resource_name "$NAMESPACE"
assert_kube_namespace_exists "$NAMESPACE" "The namespace '$NAMESPACE' does not exist"
assert_kube_resource_exists "serviceinstance/$NAME" "$NAMESPACE" "Adapter '$NAME' in namespace '$NAMESPACE' does not exist. Check created adapters running ($0 adapter list)"
}
assert_adapter_not_exists () {
local NAMESPACE="$1"
local NAME="$2"
assert_not_empty "$NAME" "Adapter name should be defined!!!"
assert_kube_resource_name "$NAME"
assert_not_empty "$NAMESPACE" "Namespace should be defined!!!"
assert_kube_resource_name "$NAMESPACE"
assert_kube_namespace_exists "$NAMESPACE" "The namespace '$NAMESPACE' does not exist"
assert_kube_resource_not_exists "serviceinstance/$NAME" "$NAMESPACE" "Adapter '$NAME' in namespace '$NAMESPACE' already created, remove it first and try again. Check created adapters running ($0 adapter list)"
}
assert_adapter_binding_exists () {
local NAMESPACE="$1"
local NAME="$2"
assert_not_empty "$NAME" "Binding Name should be defined!!!"
assert_kube_resource_name "$NAME"
assert_not_empty "$NAMESPACE" "Namespace should be defined!!!"
assert_kube_resource_name "$NAMESPACE"
assert_kube_namespace_exists "$NAMESPACE" "The namespace '$NAMESPACE' does not exist"
assert_kube_resource_exists "servicebinding/$NAME" "$NAMESPACE" "Adapter Binding '$NAME' in namespace '$NAMESPACE' does not exist. Check created binding running ($0 adapter binding list)"
}
assert_adapter_binding_not_exists () {
local NAMESPACE="$1"
local NAME="$2"
assert_not_empty "$NAME" "Binding Name should be defined!!!"
assert_kube_resource_name "$NAME"
assert_not_empty "$NAMESPACE" "Namespace should be defined!!!"
assert_kube_resource_name "$NAMESPACE"
assert_kube_namespace_exists "$NAMESPACE" "The namespace '$NAMESPACE' does not exist"
assert_kube_resource_not_exists "servicebinding/$NAME" "$NAMESPACE" "Adapter Binding '$NAME' in namespace '$NAMESPACE' already created, remove it first and try again. Check created binding running ($0 adapter binding list)"
}
assert_api_exists () {
local NAMESPACE="$1"
local NAME="$2"
assert_not_empty "$NAME" "API name should be defined!!!"
assert_kube_resource_name "$NAME"
assert_not_empty "$NAMESPACE" "Namespace should be defined!!!"
assert_kube_resource_name "$NAMESPACE"
assert_kube_namespace_exists "$NAMESPACE" "The namespace '$NAMESPACE' does not exist"
assert_kube_resource_exists "serviceinstance/$NAME" "$NAMESPACE" "API '$NAME' in namespace '$NAMESPACE' does not exist. Check created APIs running ($0 api list)"
}
assert_api_binding_exists () {
local NAMESPACE="$1"
local NAME="$2"
assert_not_empty "$NAME" "Binding Name should be defined!!!"
assert_kube_resource_name "$NAME"
assert_not_empty "$NAMESPACE" "Namespace should be defined!!!"
assert_kube_resource_name "$NAMESPACE"
assert_kube_namespace_exists "$NAMESPACE" "The namespace '$NAMESPACE' does not exist"
assert_kube_resource_exists "servicebinding/$NAME" "$NAMESPACE" "API binding '$NAME' in namespace '$NAMESPACE' does not exist. Check created API bindings running ($0 api binding list)"
}
assert_api_binding_not_exists () {
local NAMESPACE="$1"
local NAME="$2"
assert_not_empty "$NAME" "Binding Name should be defined!!!"
assert_kube_resource_name "$NAME"
assert_not_empty "$NAMESPACE" "Namespace should be defined!!!"
assert_kube_resource_name "$NAMESPACE"
assert_kube_namespace_exists "$NAMESPACE" "The namespace '$NAMESPACE' does not exist"
assert_kube_resource_not_exists "servicebinding/$NAME" "$NAMESPACE" "API binding '$NAME' in namespace '$NAMESPACE' already created, remove it first and try again.. Check created API bindings running ($0 api binding list)"
}
assert_tags () {
local VALUE="$1"
assert_pattern '^([0-9a-zA-Z]+([ ]*,[ ]*[0-9a-zA-Z]+)*)?$' "$VALUE" "Tags should be a comma separated list of strings"
}
#!/bin/sh
# --- helper functions for logs ---
_color_code() {
local severity="$1"
local color="\033[39m"
case ${severity} in
"DEBUG")
color="\033[36m"
;;
"FATAL")
color="\033[31m"
;;
"ERROR")
color="\033[31m"
;;
"INFO")
color="\033[34m"
;;
"WARN")
color="\033[33m"
;;
"START")
color="\033[32m"
;;
"FINISH")
color="\033[32m"
;;
esac
echo "${color}"
}
_logger() {
local severity="$1"; shift;
local uncolor="\033[0m"
local color=$(_color_code "${severity}")
run_and_log printf "${color}${severity}${uncolor}: $*\n" 1>&2
}
debug() {
[ "$VERBOSE" -ge 4 ] && _logger "DEBUG" "$@" || true
}
info() {
[ "$VERBOSE" -ge 3 ] && _logger "INFO" "$@" || true
}
warn() {
[ "$VERBOSE" -ge 2 ] && _logger "WARN" "$@" || true
}
error() {
[ "$VERBOSE" -ge 1 ] && _logger "ERROR" "$@" || true
}
fatal() {
_logger "FATAL" "$@" || true
exit 1
}
# runs a command and logs output to filesystem
run_and_log() {
local output
local status
local logfile="$(config_get_asm_log_file_path)"
output="$("$@" 2>&1)"
status="$?"
# send command output to stdout
echo "$output"
# save command output to log file
echo "$output" >> "$logfile"
# bubble up the command exit code
return $status
}
logger_mute () {
"$@" > /dev/null
}
# this code prints a line after each execution that will onyl be visible on log files
trap 'run_and_log printf "%0.s-" {1..128} > /dev/null' EXIT
#!/bin/sh
## test if command exists
ftest () {
debug "Checking ${1} exist..."
type "${1}" > /dev/null 2>&1 && return 0 || return 1
}
## feature tests
features () {
for f in "${@}"; do
ftest "${f}" || {
echo "Missing '${f}'! Make sure it is installed and try again."
return 1
}
done
return 0
}
is_match () {
local PATTERN="$1"
awk "/$PATTERN/{RC=0}BEGIN{RC=1}END{exit RC}" && return 0 || return $?
}
cmd_exist () {
local CMD="$1"
type "$CMD" > /dev/null 2>&1 && return 0 || return 1
}
cmd_run () {
local CMD="$1"; shift;
config_set_args "$@"
$CMD "$@" || return $?
}
main () {
local CMD="$1"; [ "$CMD" ] && shift;
CMD="${CMD:-help}"
cmd_exist "$CMD" || {
error "Unknown command '${CMD}' for '$0'. Run '$0 help' for usage."
return 1
}
cmd_run "$CMD" "$@" || return $?
}
utils_replace () {
local PATTERN="$1"
local VALUE="$2"
awk "{gsub(/$PATTERN/, \"$VALUE\")}{print }"
}
utils_get_os () {
uname -sm
}
# Call: utils_get_option ...
# Stdout: param value
# Return code: 0
utils_get_option() {
local NAME="$1"; shift;
local DEFAULT="$1"; shift;
local RESULT="$DEFAULT"
for i in "$@"; do
case $i in
${NAME}=*) # option with format --key=value
RESULT="${i#*=}"; break;
;;
${NAME}) # option with format --key value
RESULT="$2"; break;
;;
*) # unknown option
shift # past argument
;;
esac
done
debug "[utils_get_option] NAME=$NAME DEFAULT=$DEFAULT PARAMS=[$*] RESULT=[$RESULT]"
echo "$RESULT"
return 0
}
# Call: utils_get_bool_option ...
# Stdout: param value
# Return code: 0
utils_get_bool_option() {
local NAME="$1"; shift;
local RESULT=""
for i in "$@"; do
case $i in
${NAME})
RESULT="1";;
esac
done
debug "[utils_get_bool_option] NAME=$NAME PARAMS=[$*] RESULT=$RESULT"
echo "$RESULT"
return 0
}
check_not_empty() {
local VALUE="$1"
[ -z "$VALUE" ] && return 1 || return 0
}
check_file_exists() {
local VALUE="$1"
[ ! -f "$VALUE" ] && return 1 || return 0
}
check_pattern() {
local PATTERN="$1"
local VALUE="$2"
echo "$VALUE" | awk "/$PATTERN/{RC=0}BEGIN{RC=1}END{exit RC}" && return 0 || return 1
}
#!/bin/sh
# shellcheck disable=SC2039
upgrade_check_deps () {
local PLATFORM_URI="$1"
local FEATURES_ERROR_MSG
## test for require features
info "Checking dependencies..."
FEATURES_ERROR_MSG=$(features kubectl helm)
if [ "$?" -ne "0" ]; then
upgrade_failure "$PLATFORM_URI" "$FEATURES_ERROR_MSG"
fi
}
upgrade_servicemesh_upgrade() {
local PLATFORM_URI="$1"
local REASON
local SERVICE_MESH_UPGRADE_ERROR_MSG
SERVICE_MESH_UPGRADE_ERROR_MSG="$(servicemesh_upgrade "$PLATFORM_URI")"
if [ "$?" -ne "0" ]; then
REASON="$SERVICE_MESH_UPGRADE_ERROR_MSG"
upgrade_failure "$PLATFORM_URI" "$REASON"
fi
return 0;
}
upgrade_on_success() {
local PLATFORM_URI="$1"
local TIME_SPENT="$2"
local MASTER_ORGANIZATION_ID="$(config_get_master_organization_id)"
local SM_VERSION="$(version_get_number "$(helm_chart_version service-mesh-uber service-mesh)")"
local TIME_SPENT_PROPERTY="$(json_field_string "time_spent_seconds" "$TIME_SPENT")"
local SM_VERSION_PROPERTY="$(json_field_string "sm_version" "$SM_VERSION")"
local PROPERTIES="$(upgrade_event_properties "$PLATFORM_URI" "$TIME_SPENT_PROPERTY" "$SM_VERSION_PROPERTY")"
local TYPE="Successful Upgrade"
events_track_event "$PLATFORM_URI" "$PROPERTIES" "$TYPE" "$MASTER_ORGANIZATION_ID"
}
upgrade_event_properties() {
local PLATFORM_URI="$1"; shift
local CLI_VERSION="$(version_get_number "$(config_get_asm_version)")"
local KUBERNETES_VERSION="$(version_get_number "$(kube_get_version)")"
json_object \
"$(json_field_string "cli_version" "$CLI_VERSION")" \
"$(json_field_string "kubernetes_version" "$KUBERNETES_VERSION")" \
"$(json_field_string "platform_uri" "$PLATFORM_URI")" \
"${@}"
}
upgrade_on_failure() {
local PLATFORM_URI="$1"
local REASON="$2"
local MASTER_ORGANIZATION_ID="$(config_get_master_organization_id)"
local REASON_PROPERTY="$(json_field_string "reason" "$REASON")"
local PROPERTIES="$(upgrade_event_properties "$PLATFORM_URI" "$REASON_PROPERTY")"
local TYPE="Failed Upgrade"
events_track_event "$PLATFORM_URI" "$PROPERTIES" "$TYPE" "$MASTER_ORGANIZATION_ID"
}
upgrade_failure() {
local PLATFORM_URI="$1"
local REASON="$2"
upgrade_on_failure "$PLATFORM_URI" "$REASON"
fatal "$REASON"
}
upgrade () {
local PLATFORM_URI="$(config_get_option_platform_uri)"
info "Upgrading Service Mesh..."
local UPGRADE_STARTTIME="$(date +%s)"
## build
{
upgrade_check_deps "$PLATFORM_URI" \
&& upgrade_servicemesh_upgrade "$PLATFORM_URI" \
&& info "Done!" || return $?
} >&2
local UPGRADE_ENDTIME="$(date +%s)"
local TIME_SPENT="$(($UPGRADE_ENDTIME - $UPGRADE_STARTTIME))"
upgrade_on_success "$PLATFORM_URI" "$TIME_SPENT"
return $?
}
#!/bin/sh
# shellcheck disable=SC2039
adapter_binding_list () {
assert_servicemesh_is_installed
run_and_log kubectl get servicebindings --all-namespaces \
--selector 'service-mesh.mulesoft.com/kind=adapter-binding' \
--output 'custom-columns=NAMESPACE:.metadata.namespace,NAME:.metadata.name,ADAPTER:.spec.instanceRef.name,API ID:.spec.parameters.apiId,SERVICE NAME:.spec.parameters.service,STATUS:.status.conditions[?(@.type=="Ready")].reason' \
| utils_replace "InjectedBindResult" "Ready" | utils_replace "BindCallFailed" "Failed"
}
#!/bin/sh
# shellcheck disable=SC2039
api_logs () {
local NAMESPACE="$(config_get_option_namespace)"
local NAME="$(config_get_option_name)"
assert_servicemesh_is_installed
assert_api_exists "$NAMESPACE" "$NAME"
run_and_log kubectl -n "$NAMESPACE" get events --field-selector "involvedObject.name=$NAME,involvedObject.kind=ServiceInstance" -o='custom-columns=DATE:.lastTimestamp,MESSAGE:.message' --sort-by=.lastTimestamp
}
#!/bin/sh
# shellcheck disable=SC2039
management_help () {
local CMD="$(basename $0) management"
info "Usage:"
info " $CMD check (bindings|sidecar) --namespace=NAMESPACE"
info " $CMD config"
info " $CMD dump --istioNamespace=ISTIO_NAMESPACE [-f]"
info " $CMD restart ([--broker | --brokerImpl | --catalog | --istio] | --all)"
info ""
info "Options:"
info " --all Restart all Service Mesh components"
info " --broker Service Broker component"
info " --brokerImpl Service Broker Implementation component"
info " --catalog Service Catalog components"
info " -f Force dump without confirmation"
info " --istio Istio components"
info " --istioNamespace=ISTIO_NAMESPACE Where Istio is installed [default: istio-system]."
info " --namespace=NAMESPACE Kubernetes Namespace."
return $?
}
management () {
local CMD="$1"; [ "$CMD" ] && shift;
CMD="${CMD:-help}"
cmd_exist "management_$CMD" || {
error "Unknown command '${CMD}' for '$0 management'. Run '$0 management help' for usage."
return 1
}
"management_${CMD}" "$@" || return $?
}
#!/bin/sh
# shellcheck disable=SC2039
management_check_help () {
local CMD="$(basename $0) management check"
info "Usage:"
info " $CMD (bindings|sidecar) --namespace=NAMESPACE"
info ""
info "Options:"
info " --namespace=NAMESPACE Kubernetes Namespace."
return $?
}
management_check () {
local CMD="$1"; [ "$CMD" ] && shift;
CMD="${CMD:-help}"
cmd_exist "management_check_$CMD" || {
error "Unknown command '${CMD}' for '$0 management check'. Run '$0 management check help' for usage."
return 1
}
"management_check_${CMD}" "$@" || return $?
}
#!/bin/sh
# shellcheck disable=SC2039
api_update () {
local NAMESPACE="$(config_get_option_namespace)"
local NAME="$(config_get_option_name)"
local VERSION="$(utils_get_option --version "" "$@")"
local MAIN_FILE="$(utils_get_option --mainFile "" "$@")"
local SPEC_PATH="$(utils_get_option --specPath "" "$@")"
local SPEC_TAGS="$(utils_get_option --specTags "" "$@")"
local INSTANCE_TAGS="$(utils_get_option --instanceTags "" "$@")"
local API_CLASSIFIER
local SPEC_FILE_CONTENT
local UPDATE_OPS
assert_servicemesh_is_installed
assert_api_exists "$NAMESPACE" "$NAME"
assert_tags "$SPEC_TAGS"
assert_tags "$INSTANCE_TAGS"
API_CLASSIFIER="$(kube_get_resource_fields "serviceinstance/$NAME" "$NAMESPACE" "{.spec.parameters.classifier}")"
if [ "$API_CLASSIFIER" = "http" ]; then
assert_empty "$MAIN_FILE" "Main file should not be defined when asset type is http!!!"
assert_empty "$SPEC_PATH" "Spec path should not be defined when asset type is http!!!"
else
if [ ! -z $VERSION ] || [ ! -z $MAIN_FILE ] || [ ! -z $SPEC_PATH ]; then
assert_not_empty "$VERSION" "Version should change when updating the spec parameters!!!"
assert_not_empty "$MAIN_FILE" "Main file should be defined for this type of asset when updating version or specification!!!"
assert_not_empty "$SPEC_PATH" "Spec path should be defined for this type of asset when updating version or main file!!!"
assert_file_exists "$SPEC_PATH" "Spec file should exist!!"
SPEC_FILE_CONTENT="$(base64_file_encode "$SPEC_PATH")"
fi
fi
[ -n "$VERSION" ] && UPDATE_OPS="{ 'op': 'replace', 'path': '/spec/parameters/version', 'value': $VERSION }, $UPDATE_OPS"
[ -n "$MAIN_FILE" ] && UPDATE_OPS="{ 'op': 'replace', 'path': '/spec/parameters/mainFile', 'value': $MAIN_FILE }, $UPDATE_OPS"
[ -n "$SPEC_FILE_CONTENT" ] && UPDATE_OPS="{ 'op': 'replace', 'path': '/spec/parameters/specFile', 'value': $SPEC_FILE_CONTENT }, $UPDATE_OPS"
[ -n "$SPEC_TAGS" ] && UPDATE_OPS="{ 'op': 'replace', 'path': '/spec/parameters/tags/apiSpec', 'value': [$SPEC_TAGS] }, $UPDATE_OPS"
[ -n "$INSTANCE_TAGS" ] && UPDATE_OPS="{ 'op': 'replace', 'path': '/spec/parameters/tags/apiInstance', 'value': [$INSTANCE_TAGS] }, $UPDATE_OPS"
kube_patch_resource_keys "serviceinstance/$NAME" "$NAMESPACE" "$UPDATE_OPS" > /dev/null 2>&1 && {
info "Service Mesh API '$NAME' in namespace '$NAMESPACE' updated"
} || {
fatal "Updating Service Mesh API '$NAME' in namespace '$NAMESPACE'"
}
return $?
}
#!/bin/sh
# shellcheck disable=SC2039
adapter_delete () {
local NAMESPACE="$(config_get_option_namespace)"
local NAME="$(config_get_option_name)"
assert_servicemesh_is_installed
assert_adapter_exists "$NAMESPACE" "$NAME"
kubectl -n "$NAMESPACE" delete serviceinstances "$NAME" > /dev/null 2>&1 && {
info "Service Mesh Adapter '$NAME' in namespace '$NAMESPACE' deleted"
} || {
fatal "Deleting Service Mesh Adapter '$NAME' in namespace '$NAMESPACE'"
}
return 0
}
#!/bin/sh
# shellcheck disable=SC2039
# --- uninstall command ---
uninstall_check_deps () {
local FEATURES_ERROR_MSG
## test for require features
info "Checking dependencies..."
FEATURES_ERROR_MSG="$(features kubectl helm curl awk)"
if [ "$?" -ne "0" ]; then
error "$FEATURES_ERROR_MSG"
return 1
fi
}
uninstall_check_bindings () {
info "Checking for existing service bindings..."
kube_check_no_resource_exists_across_namespaces "servicebindings" || {
fatal "There are service bindings created, delete them first and try again!!!"
}
}
uninstall_check_instances () {
info "Checking for existing service instances..."
kube_check_no_resource_exists_across_namespaces "serviceinstances" || {
fatal "There are service instances created, delete them first and try again!!!"
}
}
uninstall_remove_namespace () {
info "Remove 'service-mesh' namespace..."
kube_delete 'namespace' 'service-mesh' 'all' || {
fatal "Removing 'service-mesh' namespace!!!"
}
}
uninstall () {
info "Uninstalling Service Mesh..."
## build
{
uninstall_check_deps \
&& uninstall_check_bindings \
&& uninstall_check_instances \
&& servicemesh_uninstall \
&& uninstall_remove_namespace \
&& info "Done!" || return $?
} >&2
return $?
}
#!/bin/sh
# shellcheck disable=SC2039
adapter_logs () {
local NAMESPACE="$(config_get_option_namespace)"
local NAME="$(config_get_option_name)"
assert_servicemesh_is_installed
assert_adapter_exists "$NAMESPACE" "$NAME"
run_and_log kubectl -n "$NAMESPACE" get events --field-selector "involvedObject.name=$NAME,involvedObject.kind=ServiceInstance" -o='custom-columns=DATE:.lastTimestamp,MESSAGE:.message' --sort-by=.lastTimestamp
}
#!/bin/sh
# shellcheck disable=SC2039
config () {
local CMD=$(basename $0)
info "Configuring Service Mesh..."
servicemesh_config && info "Done!" || return $?
return $?
}
#!/bin/sh
# shellcheck disable=SC2039
api_create () {
local NAMESPACE="$(config_get_option_namespace)"
local NAME="$(config_get_option_name)"
local ENVIRONMENT_ID="$(utils_get_option --environmentId "" "$@")"
local GROUP_ID="$(utils_get_option --groupId "" "$@")"
local ASSET_ID="$(utils_get_option --assetId "" "$@")"
local VERSION="$(utils_get_option --version "" "$@")"
local INSTANCE_LABEL="$(utils_get_option --instanceLabel "" "$@")"
local CLASSIFIER="$(utils_get_option --classifier "http" "$@")"
local MAIN_FILE="$(utils_get_option --mainFile "" "$@")"
local SPEC_PATH="$(utils_get_option --specPath "" "$@")"
local SPEC_TAGS="$(utils_get_option --specTags "" "$@")"
local INSTANCE_TAGS="$(utils_get_option --instanceTags "" "$@")"
local USERNAME="$(utils_get_option --user "" "$@")"
local PASSWORD="$(utils_get_option --password "" "$@")"
local CLIENT_ID="$(config_get_option_client_id)"
local CLIENT_SECRET="$(config_get_option_client_secret)"
local GROUP_ID_FIELD
local MAIN_FILE_FIELD
local SPEC_FILE_FIELD
local SPEC_FILE_CONTENT
local ID_FIELD
local SECRET_FIELD
assert_not_empty "$NAME" "API name should be defined!!!"
assert_kube_resource_name "$NAME"
assert_not_empty "$ENVIRONMENT_ID" "Environment ID should be defined!!!"
assert_not_empty "$ASSET_ID" "Asset ID should be defined!!!"
assert_not_empty "$VERSION" "Version should be defined!!!"
assert_not_empty "$INSTANCE_LABEL" "Instance label should be defined!!!"
assert_not_empty "$CLIENT_ID$CLIENT_SECRET$USERNAME$PASSWORD" "Client ID/Secret or Username/Password should be defined!!!"
if [ -z $CLIENT_ID ] && [ -z $CLIENT_SECRET ]
then
assert_not_empty "$USERNAME" "Username should be defined!!!"
assert_not_empty "$PASSWORD" "Password should be defined!!!"
ID_FIELD="user: \"${USERNAME}\""
SECRET_FIELD="password: \"${PASSWORD}\""
else
assert_empty "$USERNAME$PASSWORD" "Username/Password should not be defined when using client credentials!!!"
assert_not_empty "$CLIENT_ID" "Client ID should be defined!!!"
assert_not_empty "$CLIENT_SECRET" "Client Secret should be defined!!!"
ID_FIELD="clientId: \"${CLIENT_ID}\""
SECRET_FIELD="clientSecret: \"${CLIENT_SECRET}\""
fi
if [ "$CLASSIFIER" = "http" ]; then
assert_empty "$MAIN_FILE" "Main file should not be defined when asset type is http!!!"
assert_empty "$SPEC_PATH" "Spec path should not be defined when asset type is http!!!"
else
assert_not_empty "$MAIN_FILE" "Main file should be defined for this type of asset!!!"
assert_not_empty "$SPEC_PATH" "Spec path should be defined for this type of asset!!!"
assert_file_exists "$SPEC_PATH" "Spec file should exist!!"
MAIN_FILE_FIELD="mainFile: \"${MAIN_FILE}\""
SPEC_FILE_CONTENT="$(base64_file_encode "$SPEC_PATH")"
SPEC_FILE_FIELD="specFile: \"${SPEC_FILE_CONTENT}\""
fi
assert_tags "$SPEC_TAGS"
assert_tags "$INSTANCE_TAGS"
assert_servicemesh_is_installed
assert_kube_namespace_exists "$NAMESPACE" "The namespace '$NAMESPACE' does not exist"
assert_kube_resource_not_exists "serviceinstance/$NAME" "$NAMESPACE" "API '$NAME' already created, remove it first and try again. Check created APIs running ($0 api list)"
# only set group id field if defined
[ -n "$GROUP_ID" ] && GROUP_ID_FIELD="groupId: \"${GROUP_ID}\""
{ cat << EOF
apiVersion: servicecatalog.k8s.io/v1beta1
kind: ServiceInstance
metadata:
name: "${NAME}"
namespace: "${NAMESPACE}"
labels:
service-mesh.mulesoft.com/kind: api
spec:
clusterServiceClassExternalName: anypoint-platform-api-instance
clusterServicePlanExternalName: service-mesh
parameters:
environmentId: "${ENVIRONMENT_ID}"
${GROUP_ID_FIELD}
assetId: "${ASSET_ID}"
version: "${VERSION}"
instanceLabel: "${INSTANCE_LABEL}"
classifier: "${CLASSIFIER}"
${MAIN_FILE_FIELD}
${SPEC_FILE_FIELD}
${ID_FIELD}
${SECRET_FIELD}
tags:
apiInstance: "${INSTANCE_TAGS}"
apiSpec: "${SPEC_TAGS}"
EOF
} | kubectl create -f - > /dev/null 2>&1 && {
info "Service Mesh API '$NAME' in namespace '$NAMESPACE' created"
} || {
error "Creating Service Mesh API '$NAME' in namespace '$NAMESPACE'"
return 1
}
return $?
}
#!/bin/sh
# shellcheck disable=SC2039
management_config_log4j () {
info "The log4j config file is configured to check for changes every 60 seconds, so that should be the maximum time needed to see the modifications applied"
local NAMESPACE="$(config_get_option_namespace)"
local LOG4J_FILE="$(config_get_option_log4jfile)"
assert_not_empty "$NAMESPACE" "Namespace should be defined!!!"
assert_not_empty "$LOG4J_FILE" "Log4j file should be defined!!!"
assert_file_exists "$LOG4J_FILE" "Log4j file should exist!!!"
for podName in $(kubectl -n service-mesh get pods -l namespace="$NAMESPACE" -oname | sed -e 's/pod\///g')
do
info "> Uploading log4j file to adapter pod name $podName for namespace $NAMESPACE"
kubectl cp -c mule "$LOG4J_FILE" "service-mesh/${podName}:/usr/src/app/conf/log4j2.xml" 2> /dev/null
info "> File uploaded."
done
info "Done!"
return $?
}
#!/bin/sh
# shellcheck disable=SC2039
api_binding_delete () {
local NAMESPACE="$(config_get_option_namespace)"
local NAME="$(config_get_option_name)"
assert_servicemesh_is_installed
assert_api_binding_exists "$NAMESPACE" "$NAME"
kubectl -n "$NAMESPACE" delete servicebinding "$NAME" > /dev/null 2>&1 && {
info "Service Mesh Binding '$NAME' in namespace '$NAMESPACE' deleted"
} || {
error "Deleting Service Mesh Binding '$NAME' in namespace '$NAMESPACE'"
}
}
#!/bin/sh
# shellcheck disable=SC2039
api_binding_logs () {
local NAMESPACE="$(config_get_option_namespace)"
local NAME="$(config_get_option_name)"
assert_servicemesh_is_installed
assert_api_binding_exists "$NAMESPACE" "$NAME"
run_and_log kubectl -n "$NAMESPACE" get events --field-selector "involvedObject.name=$NAME,involvedObject.kind=ServiceBinding" -o='custom-columns=DATE:.lastTimestamp,MESSAGE:.message' --sort-by=.lastTimestamp
}
#!/bin/sh
# shellcheck disable=SC2039
management_dump () {
local TEMP_DUMP_FOLDER="$(config_get_asm_temp_dump_folder)"
local FORCE_DUMP="$(config_get_option_flag_force)"
local ISTIO_NAMESPACE="$(config_get_option_istio_namespace)"
[ "$FORCE_DUMP" ] && {
info "Disclaimer: this process cluster will extract sensitive data from cluster."
} || {
input_prompt_yes_no "Disclaimer: this process cluster will extract sensitive data from cluster. Do you want to proceed?" || return $?
}
info "Dumping Service Mesh state..."
management_dump_cluster_info "$TEMP_DUMP_FOLDER"
management_dump_api_intances "$TEMP_DUMP_FOLDER"
management_dump_adapter_intances "$TEMP_DUMP_FOLDER"
management_dump_binding_intances "$TEMP_DUMP_FOLDER"
management_dump_istio_config "$TEMP_DUMP_FOLDER" "$ISTIO_NAMESPACE"
management_dump_istio_logs "$TEMP_DUMP_FOLDER" "$ISTIO_NAMESPACE"
management_dump_catalog_resources "$TEMP_DUMP_FOLDER"
management_dump_adapter_logs "$TEMP_DUMP_FOLDER"
management_dump_adapter_policies_and_contracts "$TEMP_DUMP_FOLDER"
management_dump_asm_logs "$TEMP_DUMP_FOLDER"
management_dump_asm_config_logs "$TEMP_DUMP_FOLDER"
management_dump_connections_graph "$TEMP_DUMP_FOLDER"
info "Done!"
info "Dump available at $TEMP_DUMP_FOLDER"
return $?
}
management_dump_cluster_info () {
info "> Dumping cluster state..."
local tmp_folder="$1"
kubectl -n service-mesh cluster-info dump > "$tmp_folder/cluster_info.log"
}
management_dump_api_intances () {
info "> Dumping APIs state..."
local tmp_folder="$1"
kubectl get serviceInstances -l "service-mesh.mulesoft.com/kind=api" --all-namespaces -oyaml > "$tmp_folder/api_instances.log"
}
management_dump_adapter_intances () {
info "> Dumping adapters state..."
local tmp_folder="$1"
kubectl get serviceInstances -l "service-mesh.mulesoft.com/kind=adapter" --all-namespaces -oyaml > "$tmp_folder/adapter_instances.log"
}
management_dump_binding_intances () {
info "> Dumping bindings state..."
local tmp_folder="$1"
kubectl get servicebinding --all-namespaces -oyaml > "$tmp_folder/bindings.log"
}
management_dump_istio_config () {
info "> Dumping istio config..."
local tmp_folder="$1"
local namespace="$2"
kubectl -n "$namespace" get cm/istio -oyaml > "$tmp_folder/istio_config.log"
}
management_dump_istio_logs () {
info "> Dumping istio logs..."
local tmp_folder="$1"
local namespace="$2"
for p in $(kubectl -n "$namespace" get pods -oname | awk "/istio/"); do n=$(echo "$p" | sed -e 's/pod\///g'); kubectl -n "$namespace" --all-containers=true logs "$n" > "$tmp_folder/$n.log"; done
}
management_dump_catalog_resources () {
info "> Dumping catalog logs..."
local tmp_folder="$1"
kubectl -n service-mesh get clusterserviceclass,clusterservicebroker,clusterserviceplan -oyaml > "$tmp_folder/catalog_resources.log"
}
management_dump_adapter_logs () {
info "> Dumping adapter logs..."
local tmp_folder="$1"
for p in $(kubectl -n service-mesh get pods -oname | awk "/grpc/"); do n=$(echo "$p" | sed -e 's/pod\///g'); kubectl -n service-mesh --all-containers=true logs "$n" > "$tmp_folder/$n.log"; done
}
management_dump_asm_logs () {
info "> Dumping Service Mesh components logs..."
local tmp_folder="$1"
for p in $(kubectl -n service-mesh get pods -oname | awk "/service-mesh/"); do n=$(echo "$p" | sed -e 's/pod\///g'); kubectl -n service-mesh --all-containers=true logs "$n" > "$tmp_folder/$n.log"; done
}
management_dump_asm_config_logs () {
info "> Dumping Service Mesh config logs..."
local tmp_folder="$1"
kubectl -n service-mesh get cm -oyaml > "$tmp_folder/asm_config.log"
}
management_dump_adapter_policies_and_contracts () {
info "> Dumping adapter files..."
local tmp_folder="$1"
for p in $(kubectl -n service-mesh get pods -oname | awk "/grpc/"); do n=$(echo "$p" | sed -e 's/pod\///g'); kubectl exec -n service-mesh "$n" -c mule -- tar chf - /usr/src/app/policies -C /usr/src/app/policies > "$tmp_folder/$n-policies-folder.tar.gz" 2> /dev/null ; done
}
management_dump_connections_graph () {
local TEMP_DUMP_FOLDER="$1"
info "> Creating Connections Graph..."
echo "digraph pvn {" > "$TEMP_DUMP_FOLDER/connections-graph.dot"
info ">> Discovering PODs..."
management_dump_connections_graph_pods >> "$TEMP_DUMP_FOLDER/connections-graph.dot"
info ">> Discovering Services..."
management_dump_connections_graph_services >> "$TEMP_DUMP_FOLDER/connections-graph.dot"
info ">> Discovering Connections..."
management_dump_connections_graph_pods_connections >> "$TEMP_DUMP_FOLDER/connections-graph.dot"
echo "}" >> "$TEMP_DUMP_FOLDER/connections-graph.dot"
}
management_dump_connections_graph_pod_connections() {
local NS="$1"
local POD="$2"
kubectl exec -ti -n "$NS" "$POD" -c istio-proxy -- netstat -tn | grep -v 127.0.0 | sed 's/:/ /g' | awk '/(ESTABLISHED|TIME_WAIT)/{print "\""$4"\"->\""$6"\";"}' | sort | uniq
}
management_dump_connections_graph_service() {
local NS="$1"
local NAME="$2"
local ID="$3"
echo "\"$ID\"[color=green,label=\"{$NS|$NAME}\",shape=record];"
for EP in $(kubectl -n "$NS" get ep "$NAME" -o=go-template='{{range .subsets}}{{range .addresses}}{{.ip}}{{"\n"}}{{end}}{{end}}'); do
echo "\"$ID\" -> \"$EP\"[color=green]"
done
}
management_dump_connections_graph_pod() {
local NS="$1"
local NAME="$2"
local ID="$3"
echo "\"$ID\"[color=blue,label=\"{$NS|$NAME}\",shape=record];"
}
management_dump_connections_graph_pods() {
local POD
local NS
local ID
local NAME
for POD in $(kubectl get pod --all-namespaces --no-headers -ogo-template='{{ range .items}}{{if .status.podIP}}{{.metadata.namespace}}{{"|"}}{{.metadata.name}}{{"|"}}{{.status.podIP}}{{"\n"}}{{end}}{{end}}'); do
NS="$(echo "$POD" | awk 'BEGIN{FS="|"}{print $1}')"
NAME="$(echo "$POD" | awk 'BEGIN{FS="|"}{print $2}')"
ID="$(echo "$POD" | awk 'BEGIN{FS="|"}{print $3}')"
management_dump_connections_graph_pod "$NS" "$NAME" "$ID"
done
}
management_dump_connections_graph_services() {
local SVC
local NS
local ID
local NAME
for SVC in $(kubectl get svc --all-namespaces --no-headers -ogo-template='{{ range .items}}{{.metadata.namespace}}{{"|"}}{{.metadata.name}}{{"|"}}{{.spec.clusterIP}}{{"\n"}}{{end}}'); do
NS="$(echo "$SVC" | awk 'BEGIN{FS="|"}{print $1}')"
NAME="$(echo "$SVC" | awk 'BEGIN{FS="|"}{print $2}')"
ID="$(echo "$SVC" | awk 'BEGIN{FS="|"}{print $3}')"
management_dump_connections_graph_service "$NS" "$NAME" "$ID"
done
}
management_dump_connections_graph_pods_connections() {
local POD
local NS
local NAME
for POD in $(kubectl get pod --all-namespaces --no-headers -ogo-template='{{range $pod := .items}}{{range $pod.status.containerStatuses}}{{if eq .name "istio-proxy"}}{{$pod.metadata.namespace}}{{"|"}}{{$pod.metadata.name}}{{"\n"}}{{end}}{{end}}{{end}}'); do
NS="$(echo "$POD" | awk 'BEGIN{FS="|"}{print $1}')"
NAME="$(echo "$POD" | awk 'BEGIN{FS="|"}{print $2}')"
management_dump_connections_graph_pod_connections "$NS" "$NAME"
done
}
#!/bin/sh
# shellcheck disable=SC2039
# --- help command ---
help () {
if [ -z "$1" ]; then
help_root
else
local CMD="";
for i in "$@"; do
case $i in
--*) # flag
break;
;;
*) # command piece
if [ -z "$CMD" ]; then
CMD="$i"
else
CMD="${CMD}_$i"
fi
;;
esac
done
CMD="${CMD}_help"
cmd_exist "${CMD}" || {
error "Unknown command '$* help'. Run '$0 help' for usage."
return 1
}
"${CMD}" || return $?
fi
}
help_root () {
local CMD=$(basename $0)
info "Usage:"
info " $CMD adapter"
info " $CMD api"
info " $CMD install [--clientId=CLIENT_ID] [--clientSecret=CLIENT_SECRET] [--license=LICENSE] [--platformUri=PLATFORM_URI] [(--proxyProtocol=PROXY_PROTOCOL --proxyHost=PROXY_HOST --proxyPort=PROXY_PORT) --proxyUser=PROXY_USER --proxyPassword=PROXY_PASS] [--istioNamespace=ISTIO_NAMESPACE] [--mtls=MTLS]"
info " $CMD config [--clientId=CLIENT_ID] [--clientSecret=CLIENT_SECRET] [--mtls=MTLS]"
info " $CMD management"
info " $CMD uninstall"
info " $CMD upgrade"
info " $CMD version"
info ""
info "Options:"
info " --clientId=CLIENT_ID Organization client ID."
info " --clientSecret=CLIENT_SECRET Organization client secret."
info " --istioNamespace=ISTIO_NAMESPACE Where Istio is installed [default: istio-system]."
info " --license=LICENSE License absolute or relative path."
info " --mtls=MTLS Enable mTLS in adapter connections (enabled|disabled) [default: disabled]."
info " --platformUri=PLATFORM_URI Anypoint platform URL [default: $(config_get_option_platform_uri)]."
info " --proxyProtocol=PROXY_PROTOCOL Proxy protocol (http|https)."
info " --proxyHost=PROXY_HOST Proxy host."
info " --proxyPort=PROXY_PORT Proxy port."
info " --proxyUser=PROXY_USER Proxy user."
info " --proxyPassword=PROXY_PASS Proxy password."
info ""
info "Examples:"
info " # Install Anypoint Service Mesh"
info " $CMD install --license=./license.lic"
return $?
}
#!/bin/sh
# shellcheck disable=SC2039
install_usage () {
local CMD="$(basename $0) install"
info "Usage:"
info " $CMD help"
info " $CMD [--clientId=CLIENT_ID] [--clientSecret=CLIENT_SECRET] [--license=LICENSE] [--platformUri=PLATFORM_URI] [(--proxyProtocol=PROXY_PROTOCOL --proxyHost=PROXY_HOST --proxyPort=PROXY_PORT) --proxyUser=PROXY_USER --proxyPassword=PROXY_PASS] [--istioNamespace=ISTIO_NAMESPACE] [--mtls=MTLS] [--skipResourceChecks]"
info ""
info "Options:"
info " --clientId=CLIENT_ID Organization client ID."
info " --clientSecret=CLIENT_SECRET Organization client secret."
info " --istioNamespace=ISTIO_NAMESPACE Where Istio is installed [default: istio-system]."
info " --license=LICENSE License absolute or relative path."
info " --mtls=MTLS Enable mTLS in adapter connections (enabled|disabled) [default: disabled]."
info " --platformUri=PLATFORM_URI Anypoint platform URL [default: $(config_get_option_platform_uri)]."
info " --proxyProtocol=PROXY_PROTOCOL Proxy protocol (http|https)."
info " --proxyHost=PROXY_HOST Proxy host."
info " --proxyPort=PROXY_PORT Proxy port."
info " --proxyUser=PROXY_USER Proxy user."
info " --proxyPassword=PROXY_PASS Proxy password."
info " --skipResourceChecks If specified, skips resource availability checks"
info ""
info "Examples:"
info " # Install Anypoint Service Mesh"
info " $CMD"
return $?
}
# --- install command ---
install_check_deps () {
local PLATFORM_URI="$1"
local FEATURES_ERROR_MSG
## test for require features
info "Checking dependencies..."
FEATURES_ERROR_MSG=$(features kubectl helm curl awk base64 jq)
if [ "$?" -ne "0" ]; then
install_failure "$PLATFORM_URI" "$FEATURES_ERROR_MSG"
fi
}
install_check_config () {
local PLATFORM_URI="$1"
## test for require features
info "Checking Configuration..."
[ "$LICENSE_RAW" ] || {
check_not_empty "$LICENSE_PATH" || install_failure "$PLATFORM_URI" "License path should be defined!!!"
check_file_exists "$LICENSE_PATH" || install_failure "$PLATFORM_URI" "License file not found!!!"
}
if [ -n "$PROXY_PROTOCOL" ] || [ -n "$PROXY_HOST" ] || [ -n "$PROXY_PORT" ]
then
check_not_empty "$PROXY_PROTOCOL" || install_failure "$PLATFORM_URI" "When setting proxy, protocol should be defined!!!"
check_not_empty "$PROXY_HOST" || install_failure "$PLATFORM_URI" "When setting proxy, host should be defined!!!"
check_not_empty "$PROXY_PORT" || install_failure "$PLATFORM_URI" "When setting proxy, port should be defined!!!"
check_pattern "$SUPPORTED_PROXY_PROTOCOLS" "$PROXY_PROTOCOL" || install_failure "$PLATFORM_URI" "Proxy protocol should be http|https"
if [ -n "$PROXY_USER" ] || [ -n "$PROXY_PASSWORD" ]
then
check_not_empty "$PROXY_USER" || install_failure "$PLATFORM_URI" "When setting proxy password, user should be defined!!!"
check_not_empty "$PROXY_PASSWORD" || install_failure "$PLATFORM_URI" "When setting proxy user, password should be defined!!!"
fi
fi
}
install_check_credentials () {
local PLATFORM_URI="$1"
info "Checking Client credentials..."
check_not_empty "$SERVICEMESH_CLIENT_ID" || install_failure "$PLATFORM_URI" "SERVICEMESH_CLIENT_ID should be defined!!!"
check_not_empty "$SERVICEMESH_CLIENT_SECRET" || install_failure "$PLATFORM_URI" "SERVICEMESH_CLIENT_SECRET should be defined!!!"
}
install_check_user_role () {
local PLATFORM_URI="$1"
## test for require features
info "Checking kubernetes user role..."
kube_check_permission '*' '*' 'all' || {
install_failure "$PLATFORM_URI" "You need 'cluster-admin' role to install Service Mesh!!!"
}
}
install_check_supported_versions () {
local PLATFORM_URI="$1"
local ISTIO_NAMESPACE="$2"
local SUPPORTED_VERSIONS
SUPPORTED_VERSIONS="$(config_get_supported_versions "$PLATFORM_URI")"
if [ "$?" -ne "0" ]; then
# if config_get_supported_versions fails it returns the error message
REASON="$SUPPORTED_VERSIONS"
install_failure "$PLATFORM_URI" "$REASON"
fi
config_set_supported_versions "$SUPPORTED_VERSIONS"
install_check_kube_version "$PLATFORM_URI" && install_check_istio_version "$ISTIO_NAMESPACE" "$PLATFORM_URI"
}
install_check_kube_version () {
local PLATFORM_URI="$1"
## test for require features
info "Checking kubernetes supported version..."
kube_check_version || {
local VERSIONS="$(config_get_kube_supported_versions)"
install_failure "$PLATFORM_URI" "You need a Kubernetes version within: [ $VERSIONS ] to install Service Mesh!!!"
}
}
install_check_istio_version () {
local NAMESPACE="$1"
local PLATFORM_URI="$2"
info "Checking Istio supported version..."
istio_check_version "$NAMESPACE" || {
local VERSIONS="$(config_get_istio_supported_versions)"
install_failure "$PLATFORM_URI" "You need an Istio version within: [ $VERSIONS ] to install Service Mesh!!!"
}
}
install_check_helm_version () {
local PLATFORM_URI="$1"
local VERSIONS=$(config_get_helm_supported_versions)
## test for require features
info "Checking helm supported version..."
helm_check_client_version || {
install_failure "$PLATFORM_URI" "You need helm version ~ $VERSIONS to install Service Mesh!!!"
}
}
install_create_namespace () {
local PLATFORM_URI="$1"
info "Create 'service-mesh' namespace..."
kube_create_namespace 'service-mesh' || {
install_failure "$PLATFORM_URI" "Creating 'service-mesh' namespace!!!"
}
kube_add_label 'ns' 'service-mesh' 'istio-injection' 'enabled' || {
install_failure "$PLATFORM_URI" "Adding istio-injection label to 'service-mesh' namespace!!!"
}
}
install_setup_activation_data () {
local PLATFORM_URI="$1"
local DATA
local REASON
DATA="$(config_get_activation_data "$PLATFORM_URI" "$SERVICEMESH_CLIENT_ID" "$SERVICEMESH_CLIENT_SECRET")"
if [ "$?" -ne "0" ]; then
# if config_get_activation_data fails it returns the error message
REASON="$DATA"
install_failure "$PLATFORM_URI" "$REASON"
fi
config_set_activation_data "$DATA"
return 0;
}
install_servicemesh_install() {
local PLATFORM_URI="$1"
local REASON
local SERVICE_MESH_INSTALL_ERROR_MSG
SERVICE_MESH_INSTALL_ERROR_MSG="$(servicemesh_install "$PLATFORM_URI")"
if [ "$?" -ne "0" ]; then
REASON="$SERVICE_MESH_INSTALL_ERROR_MSG"
install_failure "$PLATFORM_URI" "$REASON"
fi
return 0;
}
install_on_success() {
local PLATFORM_URI="$1"
local TIME_SPENT="$2"
local MASTER_ORGANIZATION_ID="$(config_get_master_organization_id)"
local SM_VERSION="$(version_get_number "$(helm_chart_version service-mesh-uber service-mesh)")"
local TIME_SPENT_PROPERTY="$(json_field_string "time_spent_seconds" "$TIME_SPENT")"
local SM_VERSION_PROPERTY="$(json_field_string "sm_version" "$SM_VERSION")"
local PROPERTIES="$(install_event_properties "$PLATFORM_URI" "$TIME_SPENT_PROPERTY" "$SM_VERSION_PROPERTY")"
local TYPE="Successful Installation"
events_track_event "$PLATFORM_URI" "$PROPERTIES" "$TYPE" "$MASTER_ORGANIZATION_ID"
}
install_event_properties() {
local PLATFORM_URI="$1"; shift
local CLI_VERSION="$(version_get_number "$(config_get_asm_version)")"
local KUBERNETES_VERSION="$(version_get_number "$(kube_get_version)")"
json_object \
"$(json_field_string "cli_version" "$CLI_VERSION")" \
"$(json_field_string "kubernetes_version" "$KUBERNETES_VERSION")" \
"$(json_field_string "platform_uri" "$PLATFORM_URI")" \
"${@}"
}
install_on_failure() {
local PLATFORM_URI="$1"
local REASON="$2"
local MASTER_ORGANIZATION_ID="$(config_get_master_organization_id)"
local REASON_PROPERTY="$(json_field_string "reason" "$REASON")"
local PROPERTIES="$(install_event_properties "$PLATFORM_URI" "$REASON_PROPERTY")"
local TYPE="Failed Installation"
events_track_event "$PLATFORM_URI" "$PROPERTIES" "$TYPE" "$MASTER_ORGANIZATION_ID"
}
install_failure() {
local PLATFORM_URI="$1"
local REASON="$2"
install_on_failure "$PLATFORM_URI" "$REASON"
fatal "$REASON"
}
install () {
local CMD="$1";
CMD="${CMD:-install}"
[ "$CMD" = "help" ] && install_usage && return $?
local ISTIO_NAMESPACE="$(config_get_option_istio_namespace)"
local PLATFORM_URI="$(config_get_option_platform_uri)"
# TODO: refactor all this variables to local
LICENSE_PATH="$(config_get_option_license)"
PROXY_PROTOCOL="$(config_get_option_proxy_protocol)"
PROXY_HOST="$(config_get_option_proxy_host)"
PROXY_PORT="$(config_get_option_proxy_port)"
PROXY_USER="$(config_get_option_proxy_user)"
PROXY_PASSWORD="$(config_get_option_proxy_password)"
assert_platform_uri "$PLATFORM_URI"
info "Welcome to Service Mesh installer!"
SERVICEMESH_CLIENT_ID="$(config_get_option_client_id_or_prompt)"
SERVICEMESH_CLIENT_SECRET="$(config_get_option_client_secret_or_prompt)"
[ "$LICENSE_RAW" ] || {
LICENSE_PATH=${LICENSE_PATH:-$(input_path "Please enter the path to your Service Mesh license")}
}
debug "[install]" \
"CLIENT_ID=$SERVICEMESH_CLIENT_ID" \
"CLIENT_SECRET=$SERVICEMESH_CLIENT_SECRET" \
"LICENSE_PATH=$LICENSE_PATH" \
"SERVICEMESH_PLATFORM_URI=$PLATFORM_URI" \
"PROXY_PROTOCOL=$PROXY_PROTOCOL" \
"PROXY_HOST=$PROXY_HOST" \
"PROXY_PORT=$PROXY_PORT" \
"PROXY_USER=$PROXY_USER" \
"PROXY_PASSWORD=$PROXY_PASSWORD"
servicemesh_is_installed && {
info "> Service Mesh already installed"
return 0
}
local INSTALL_STARTTIME="$(date +%s)"
## build
{
info "Installing Service Mesh..." \
&& install_check_credentials "$PLATFORM_URI" \
&& install_check_config "$PLATFORM_URI" \
&& install_setup_activation_data "$PLATFORM_URI" \
&& install_check_deps "$PLATFORM_URI" \
&& install_check_supported_versions "$PLATFORM_URI" "$ISTIO_NAMESPACE" \
&& install_check_helm_version "$PLATFORM_URI" \
&& install_check_user_role "$PLATFORM_URI" \
&& install_create_namespace "$PLATFORM_URI" \
&& install_servicemesh_install "$PLATFORM_URI" \
&& info "Done!" || return $?
} >&2
local INSTALL_ENDTIME="$(date +%s)"
local TIME_SPENT="$(($INSTALL_ENDTIME - $INSTALL_STARTTIME))"
install_on_success "$PLATFORM_URI" "$TIME_SPENT"
return $?
}
#!/bin/sh
# shellcheck disable=SC2039
adapter_binding_delete () {
local NAMESPACE="$(config_get_option_namespace)"
local NAME="$(config_get_option_name)"
assert_not_empty "$NAME" "Service binding name should be defined!!!"
assert_servicemesh_is_installed
assert_adapter_binding_exists "$NAMESPACE" "$NAME"
kubectl -n "$NAMESPACE" delete servicebinding "$NAME" > /dev/null 2>&1 && {
info "Service Mesh Binding '$NAME' in namespace '$NAMESPACE' deleted"
} || {
error "Deleting Service Mesh Binding '$NAME' in namespace '$NAMESPACE'"
}
}
#!/bin/sh
version () {
local ASM_VERSION="$(config_get_asm_version)"
local KUBERNETES_VERSION="$(kube_get_version)"
local SERVICEMESH_VERSION="$(helm_chart_version service-mesh-uber service-mesh)"
printf "Service Mesh Client:%s Server:%s Kubernetes:%s\n" \
"${ASM_VERSION}" \
"${SERVICEMESH_VERSION:-NotInstalled}" \
"${KUBERNETES_VERSION}" \
1>&2
return $?
}
version_get_number() {
local VERSION="$1"
echo "$VERSION" | awk 'match($0,/[0-9]+(\.[0-9]+)+.*/) {print substr($0,RSTART,RLENGTH)}'
}
#!/bin/sh
# shellcheck disable=SC2039,SC2155,SC2015
adapter_create () {
local NAMESPACE="$(config_get_option_namespace)"
local NAME="$(config_get_option_name)"
local CLIENT_ID="$(config_get_option_client_id)"
local CLIENT_SECRET="$(config_get_option_client_secret)"
local ADAPTER_SIZE="$(config_get_option_adapter_size)"
local ADAPTER_REPLICAS="$(config_get_option_adapter_replicas)"
assert_not_empty "$NAME" "Adapter name should be defined!!!"
assert_kube_resource_name "$NAME"
assert_not_empty "$CLIENT_ID" "Client Id should be defined!!!"
assert_not_empty "$CLIENT_SECRET" "Client Secret should be defined!!!"
assert_adapter_replicas "$ADAPTER_REPLICAS"
assert_servicemesh_is_installed
assert_adapter_not_exists "$NAMESPACE" "$NAME"
adapter_check_resources "$ADAPTER_SIZE" "$ADAPTER_REPLICAS" || return $?
{ cat << EOF
apiVersion: servicecatalog.k8s.io/v1beta1
kind: ServiceInstance
metadata:
name: "${NAME}"
namespace: "${NAMESPACE}"
labels:
service-mesh.mulesoft.com/kind: adapter
spec:
clusterServiceClassExternalName: anypoint-service-mesh-adapter
clusterServicePlanExternalName: "${ADAPTER_SIZE}"
parameters:
clientId: "${CLIENT_ID}"
clientSecret: "${CLIENT_SECRET}"
replication:
replicas: ${ADAPTER_REPLICAS}
EOF
} | kubectl apply -f - > /dev/null 2>&1 && {
adapter_on_create_ok "$NAMESPACE" "$NAME" "$CLIENT_ID" "$CLIENT_SECRET" "$ADAPTER_SIZE" "$ADAPTER_REPLICAS"
info "Service Mesh Adapter '$NAME' with clientId=$CLIENT_ID and $ADAPTER_REPLICAS replica(s) in namespace '$NAMESPACE' created"
} || {
error "Creating Service Mesh Adapter '$NAME' with clientId=$CLIENT_ID and $ADAPTER_REPLICAS replica(s) in namespace '$NAMESPACE'"
return 1
}
return $?
}
adapter_on_create_ok() {
adapter_on_create_ok_add_label "$@"
openshift_on_adapter_create_ok "$@"
}
adapter_on_create_ok_add_label() {
local NAMESPACE="$1"
kube_add_label "namespace" "$NAMESPACE" "istio-injection" "enabled" || {
warn "Failed to add 'istio-injection' label needed by Istio in namespace '$NAMESPACE'"
warn "Check if you have enough permission with 'kubectl auth can-i label namespace/$NAMESPACE -A' and then run 'kubectl label namespace/$NAMESPACE istio-injection=enabled' to fix it"
return 1
}
}
adapter_check_resources () {
[ "$(config_get_option_skip_resource_checks)" ] && return 0
# be optimistic and silently succeed if user misses some of the permissions to check resources
cluster_resources_authorize || return 0
local ADAPTER_SIZE="$1"
local ADAPTER_REPLICAS="$2"
local cpu="$(adapter_get_cpu_request "$ADAPTER_SIZE" "$ADAPTER_REPLICAS")"
local mem="$(adapter_get_mem_request "$ADAPTER_SIZE" "$ADAPTER_REPLICAS")"
cluster_resources_check_prompt "create a $ADAPTER_SIZE adapter with $ADAPTER_REPLICAS replicas" "$cpu" "$mem" || return $?
}
adapter_get_cpu_request () {
local ADAPTER_SIZE="$1"
local ADAPTER_REPLICAS="$2"
local cpu
case "$ADAPTER_SIZE" in
"small") cpu="$((ADAPTER_REPLICAS * 500))m";;
"medium") cpu="$((ADAPTER_REPLICAS * 1))";;
"large") cpu="$((ADAPTER_REPLICAS * 2))";;
esac
echo "$cpu"
}
adapter_get_mem_request () {
local ADAPTER_SIZE="$1"
local ADAPTER_REPLICAS="$2"
local mem
case "$ADAPTER_SIZE" in
"small") mem="$((ADAPTER_REPLICAS * 1))Gi" ;;
"medium") mem="$((ADAPTER_REPLICAS * 1536))Mi" ;;
"large") mem="$((ADAPTER_REPLICAS * 2))Gi" ;;
esac
echo "$mem"
}
#!/bin/sh
# shellcheck disable=SC2039
api_help () {
local CMD="$(basename $0) api"
info "Usage:"
info " $CMD binding"
info " $CMD create --namespace=NAMESPACE --name=NAME --environmentId=ENVIRONMENT_ID --assetId=ASSET_ID --version=VERSION --instanceLabel=INSTANCE_LABEL [--clientId=CLIENT_ID --clientSecret=CLIENT_SECRET | --user=USER --password=PASSWORD] [--specTags=SPEC_TAGS] [--instanceTags=INSTANCE_TAGS] [--groupId=GROUP_ID] [--classifier=CLASSIFIER] [--mainFile=MAIN_FILE] [--specPath=SPEC_FILE_PATH]"
info " $CMD update --namespace=NAMESPACE --name=NAME [--version=VERSION [--mainFile=MAIN_FILE --specPath=SPEC_FILE_PATH]] [--specTags=SPEC_TAGS] [--instanceTags=INSTANCE_TAGS]"
info " $CMD delete --namespace=NAMESPACE --name=NAME"
info " $CMD logs --namespace=NAMESPACE --name=NAME"
info " $CMD list"
info ""
info "Options:"
info " --assetId=ASSET_ID The asset identifier on Exchange."
info " --classifier=CLASSIFIER Type of API specification to be created. Options: (http | oas | raml)."
info " --clientId=CLIENT_ID Client ID of the Anypoint connected app creating the API instance."
info " --clientSecret=CLIENT_SECRET Secret of the Anypoint connected app creating the API instance."
info " --environmentId=ENVIRONMENT_ID The environment ID where the API will be created."
info " --groupId=GROUP_ID The group identifier of the asset."
info " --instanceLabel=INSTANCE_LABEL The identifier of the instance on API Manager."
info " --instanceTags=INSTANCE_TAGS List of comma separated tags that will be added to the instance on API Manager."
info " --mainFile=MAIN_FILE Name of the main file in the API specification file."
info " --name=NAME API name."
info " --namespace=NAMESPACE Kubernetes Namespace."
info " --password=PASSWORD Password of the Anypoint user creating the API instance."
info " --specPath=SPEC_FILE_PATH Path to the API specification file."
info " --specTags=SPEC_TAGS List of comma separated tags that will be added to the asset on Exchange."
info " --user=USER Username of the Anypoint user creating the API instance."
info " --version=VERSION The asset version on Exchange."
info ""
info "Examples:"
info " # Create a new API"
info " $CMD create --namespace=nto-payment --name=customer-api --environmentId=907a3a35-ea7b-4aba-a320-beb129378dc8 --groupId=a58c0595-1a60-4aca-bee3-c3a45cc1525f --assetId=customer --version=1.0.0 --instanceLabel=v1 --clientId=cbe07754756c48d986bcc471f8980562 --clientSecret=6015115F8621422B9a94F4176c68c5f5"
info " $CMD create --namespace=nto-payment --name=customer-api --environmentId=907a3a35-ea7b-4aba-a320-beb129378dc8 --assetId=customer --version=1.0.0 --instanceLabel=v1 --classifier=oas --mainFile=api.yaml --specPath=/path/to/api.yaml --user=test --password=1234"
info ""
info " # Show API logs"
info " $CMD logs --namespace=nto-payment --name=customer-api"
info ""
info " # Delete an API"
info " $CMD delete --namespace=nto-payment --name=customer-api"
info ""
info " # Update an API"
info " $CMD update --namespace=nto-payment --name=customer-api --version=1.0.1 --mainFile=api_v2.yaml --specPath=/path/to/api_v2.zip --specTags=oldSpecTag,newSpecTag"
info " $CMD update --namespace=nto-payment --name=customer-api --specTags=oldSpecTag,newSpecTag --instanceTags=newTag1,newTag2"
info ""
info " # List all created APIs"
info " $CMD list"
return $?
}
api () {
local CMD="$1"; [ "$CMD" ] && shift;
CMD="${CMD:-help}"
cmd_exist "api_$CMD" || {
error "Unknown command '${CMD}' for '$0 api'. Run '$0 api help' for usage."
return 1
}
"api_${CMD}" "$@" || return $?
}
#!/bin/sh
# shellcheck disable=SC2039
api_binding_create () {
local NAMESPACE="$(config_get_option_namespace)"
local NAME="$(config_get_option_name)"
local ADAPTER="$(config_get_option_adapter_name)"
local API="$(config_get_option_api_name)"
local SERVICE_NAME="$(config_get_option_service_name)"
assert_not_empty "$NAME" "Service binding name should be defined!!!"
assert_kube_resource_name "$NAME"
assert_not_empty "$API" "API name should be defined!!!"
assert_kube_resource_name "$API"
assert_not_empty "$SERVICE_NAME" "Service name should be defined!!!"
assert_kube_resource_name "$SERVICE_NAME"
assert_servicemesh_is_installed
assert_adapter_exists "$NAMESPACE" "$ADAPTER"
assert_api_exists "$NAMESPACE" "$ADAPTER"
assert_adapter_binding_not_exists "$NAMESPACE" "$NAME"
{ cat << EOF
apiVersion: servicecatalog.k8s.io/v1beta1
kind: ServiceBinding
metadata:
name: "${NAME}"
namespace: "${NAMESPACE}"
labels:
service-mesh.mulesoft.com/kind: api-binding
spec:
instanceRef:
name: "${API}"
parameters:
adapter: "${ADAPTER}"
service: "${SERVICE_NAME}"
EOF
} | kubectl apply -f - > /dev/null 2>&1 && {
info "Service Mesh Binding '$NAME' with adapter=$ADAPTER, api=$API, service=$SERVICE_NAME in namespace '$NAMESPACE' created"
} || {
error "Creating Service Mesh Binding '$NAME' with adapter=$ADAPTER, api=$API, service=$SERVICE_NAME in namespace '$NAMESPACE'"
return 1
}
return $?
}
#!/bin/sh
# shellcheck disable=SC2039
api_list () {
assert_servicemesh_is_installed
run_and_log kubectl get serviceinstances --all-namespaces \
--selector 'service-mesh.mulesoft.com/kind=api' \
--output 'custom-columns=NAMESPACE:.metadata.namespace,NAME:.metadata.name,ENVIRONMENT ID:.spec.parameters.environmentId,ASSET ID:.spec.parameters.assetId,VERSION:.spec.parameters.version,INSTANCE LABEL:.spec.parameters.instanceLabel,STATUS:.status.conditions[?(@.type=="Ready")].reason' \
| utils_replace "ProvisionedSuccessfully" "Ready" | utils_replace "InstanceUpdatedSuccessfully" "Ready" | utils_replace "OrphanMitigationSuccessful" "Failed"
}
#!/bin/sh
# shellcheck disable=SC2039
management_config_help () {
local CMD="$(basename $0) management config"
info "Usage:"
info " $CMD license --license=LICENSE [-f]"
info " $CMD log4j --namespace=NAMESPACE --log4jFile=LOG4J_FILE"
info ""
info "Options:"
info " -f Force license edit without confirmation."
info " --namespace=NAMESPACE Kubernetes Namespace where adapter was provisioned."
info " --license=LICENSE License file path."
info " --log4jFile=LOG4J_FILE Log4j file to upload."
return 0
}
management_config () {
local CMD="${1//-/_}"; [ "$CMD" ] && shift;
CMD="${CMD:-help}"
cmd_exist "management_config_$CMD" || {
error "Unknown command '${CMD}' for '$0 management config'. Run '$0 management config help' for usage."
return 1
}
"management_config_${CMD}" "$@" || return $?
}
#!/bin/sh
# shellcheck disable=SC2039
adapter_help () {
local CMD="$(basename $0) adapter"
info "Usage:"
info " $CMD list"
info " $CMD sizes"
info " $CMD binding"
info " $CMD create --namespace=NAMESPACE --name=NAME --clientId=CLIENT_ID --clientSecret=CLIENT_SECRET --size=SIZE --replicas=REPLICAS"
info " $CMD delete --namespace=NAMESPACE --name=NAME"
info " $CMD logs --namespace=NAMESPACE --name=NAME"
info ""
info "Options:"
info " --clientId=CLIENT_ID Client Id."
info " --clientSecret=CLIENT_SECRET Client Secret."
info " --name=NAME Adapter name."
info " --namespace=NAMESPACE Kubernetes Namespace."
info " --replicas=REPLICAS Number of replicas [1..8] [default: 2]."
info " --size=SIZE Adapter Size. See '$CMD sizes' [default: medium]."
info " --skipResourceChecks If specified, skips resource availability checks"
info ""
info "Examples:"
info " # Create a new Adapter"
info " $CMD create --namespace=nto-payment --name=adapter --clientId=1234abc1234abc1234abc1234abc1234 --clientSecret=def5678def5678def5678def5678def5 --size=small --replicas=1"
info ""
info " # Show Adapter logs"
info " $CMD logs --namespace=nto-payment --name=adapter"
info ""
info " # Delete an Adapter"
info " $CMD delete --namespace=nto-payment --name=adapter"
info ""
info " # List all created Adapters"
info " $CMD list"
return $?
}
adapter () {
local CMD="$1"; [ "$CMD" ] && shift;
CMD="${CMD:-help}"
cmd_exist "adapter_$CMD" || {
error "Unknown command '${CMD}' for '$0 adapter'. Run '$0 adapter help' for usage."
return 1
}
"adapter_${CMD}" "$@" || return $?
}
#!/bin/sh
# shellcheck disable=SC2039
management_config_license () {
local licensePath="$(config_get_option_license)"
local force="$(config_get_option_flag_force)"
debug "[management_config_license] force=$force license=$licensePath"
assert_not_empty "$licensePath" "License path should be defined!!!"
assert_file_exists "$licensePath" "License file should exist!!!"
[ "$force" ] && {
info "Disclaimer: this process will restart adapter instances."
} || {
input_prompt_yes_no "Disclaimer: this process will restart adapter instances. Do you want to proceed?" || return $?
}
info "Creating new license secret ..."
local digest="$(license_digest "$licensePath")"
kube_create_secret "service-mesh-incluster-broker-impl-license" "service-mesh" "license" "$digest"
info "Restart adapter instances ..."
kubectl -n service-mesh rollout restart $(kubectl -n service-mesh get deploy -l "serviceId=4f6e6cf6-ffdd-425f-a2c7-3c9258ad246a" -oname) > /dev/null
info "Done!"
return $?
}
#!/bin/sh
# shellcheck disable=SC2039
adapter_binding_logs () {
local NAMESPACE="$(config_get_option_namespace)"
local NAME="$(config_get_option_name)"
assert_servicemesh_is_installed
assert_adapter_binding_exists "$NAMESPACE" "$NAME"
run_and_log kubectl -n "$NAMESPACE" get events --field-selector "involvedObject.name=$NAME,involvedObject.kind=ServiceBinding" -o='custom-columns=DATE:.lastTimestamp,MESSAGE:.message' --sort-by=.lastTimestamp
}
#!/bin/sh
# shellcheck disable=SC2039
adapter_binding_create () {
local NAMESPACE="$(config_get_option_namespace)"
local NAME="$(config_get_option_name)"
local ADAPTER="$(config_get_option_adapter_name)"
local API_ID="$(config_get_option_api_id)"
local SERVICE_NAME="$(config_get_option_service_name)"
assert_not_empty "$NAME" "Service binding name should be defined!!!"
assert_kube_resource_name "$NAME"
assert_not_empty "$API_ID" "API ID should be defined!!!"
assert_pattern "^[0-9]+$" "$API_ID" "API ID should be a number!!!"
assert_not_empty "$SERVICE_NAME" "Service name should be defined!!!"
assert_kube_resource_name "$SERVICE_NAME"
assert_servicemesh_is_installed
assert_adapter_exists "$NAMESPACE" "$ADAPTER"
assert_adapter_binding_not_exists "$NAMESPACE" "$NAME"
{ cat << EOF
apiVersion: servicecatalog.k8s.io/v1beta1
kind: ServiceBinding
metadata:
name: "${NAME}"
namespace: "${NAMESPACE}"
labels:
service-mesh.mulesoft.com/kind: adapter-binding
spec:
instanceRef:
name: "${ADAPTER}"
parameters:
apiId: ${API_ID}
service: "${SERVICE_NAME}"
EOF
} | kubectl apply -f - > /dev/null 2>&1 && {
info "Service Mesh Binding '$NAME' with adapter=$ADAPTER, apiId=$API_ID, service=$SERVICE_NAME in namespace '$NAMESPACE' created"
} || {
error "Creating Service Mesh Binding '$NAME' with with adapter=$ADAPTER, apiId=$API_ID, service=$SERVICE_NAME in namespace '$NAMESPACE'"
return 1
}
return $?
}
#!/bin/sh
# shellcheck disable=SC2039
adapter_list () {
assert_servicemesh_is_installed
run_and_log kubectl get serviceinstances --all-namespaces \
--selector 'service-mesh.mulesoft.com/kind=adapter' \
--output 'custom-columns=NAMESPACE:.metadata.namespace,NAME:.metadata.name,SIZE:.spec.clusterServicePlanExternalName,REPLICAS:.spec.parameters.replication.replicas,STATUS:.status.conditions[?(@.type=="Ready")].reason' \
| utils_replace "ProvisionedSuccessfully" "Ready" | utils_replace "OrphanMitigationSuccessful" "Failed"
}
#!/bin/sh
# shellcheck disable=SC2039
management_check_bindings () {
local NAMESPACE="$(config_get_option_namespace)"
info "Running bindings checks for namespace $NAMESPACE ..."
management_check_bindings_check "$NAMESPACE"
info "Done!"
return $?
}
management_check_bindings_check () {
local NAMESPACE=$1
local svcName
local portName
for bindingName in $(kubectl get servicebinding -n "$NAMESPACE" -o name)
do
info "> Checking binding: $bindingName"
svcName=$(kubectl get "$bindingName" -n "$NAMESPACE" -o go-template="{{.spec.parameters.service}}")
kube_check_resource_exists_by_name "svc/$svcName" "$NAMESPACE" && {
info "> Service found: $svcName"
portName=$(kubectl -n "$NAMESPACE" get svc "$svcName" -o go-template="{{range .spec.ports}}{{.name}} {{end}}")
echo "$portName" | is_match "(http|https)" \
&& info "> Service name found: $portName" \
|| error "> Service port name missing or not configured properly, please name your API service port name with \"http\" or \"https\""
} || {
error "Binding $bindingName references not existant service: $svcName"
}
info ""
done
}
#!/bin/sh
# shellcheck disable=SC2039
api_binding_help () {
local CMD="$(basename $0) api binding"
info "Usage:"
info " $CMD list"
info " $CMD create --namespace=NAMESPACE --name=NAME --adapter=ADAPTER --api=API_NAME --serviceName=SERVICE"
info " $CMD delete --namespace=NAMESPACE --name=NAME"
info " $CMD logs --namespace=NAMESPACE --name=NAME"
info ""
info "Options:"
info " --adapter=ADAPTER Name of the adapter."
info " --api=API_NAME API Name from API Manager."
info " --name=NAME Service binding name."
info " --namespace=NAMESPACE Kubernetes Namespace."
info " --serviceName=SERVICE Kubernetes Service name."
info ""
info "Examples:"
info " # Create a new Service Binding"
info " $CMD create --namespace=nto-payment --name=customer --adapter=adapter --api=customer-api --serviceName=customer-service"
info ""
info " # Show Service Binding logs"
info " $CMD logs --namespace=nto-payment --name=customer"
info ""
info " # Delete a Service Binding"
info " $CMD delete --namespace=nto-payment --name=customer"
info ""
info " # List all created Service Bindings"
info " $CMD list"
return $?
}
api_binding () {
local CMD="$1"; [ "$CMD" ] && shift;
CMD="${CMD:-help}"
cmd_exist "api_binding_$CMD" || {
error "Unknown command '${CMD}' for '$0 api binding'. Run '$0 api binding help' for usage."
return 1
}
"api_binding_${CMD}" "$@" || return $?
}
#!/bin/sh
# shellcheck disable=SC2039
api_delete () {
local NAMESPACE="$(config_get_option_namespace)"
local NAME="$(config_get_option_name)"
assert_servicemesh_is_installed
assert_api_exists "$NAMESPACE" "$NAME"
kube_check_resource_exists_by_name "namespace/$NAMESPACE" "all" || {
fatal "The namespace '$NAMESPACE' does not exist"
}
kube_check_resource_exists_by_name "serviceinstance/$NAME" "$NAMESPACE" || {
fatal "The Service Mesh API '$NAME' in namespace '$NAMESPACE' does not exist"
}
kubectl -n "$NAMESPACE" delete serviceinstances "$NAME" > /dev/null 2>&1 && {
info "Service Mesh API '$NAME' in namespace '$NAMESPACE' deleted"
} || {
fatal "Deleting Service Mesh API '$NAME' in namespace '$NAMESPACE'"
}
return 0
}
#!/bin/sh
# shellcheck disable=SC2039
management_restart_help () {
local CMD="$(basename $0) management restart"
info "Usage:"
info " $CMD ([--broker | --brokerImpl | --catalog | --istio] | --all)"
info ""
info "Options:"
info " --all Restart all Service Mesh components"
info " --broker Service Broker component"
info " --brokerImpl Service Broker Implementation component"
info " --catalog Service Catalog components"
info " --istio Istio components"
info " --istioNamespace=ISTIO_NAMESPACE Where Istio is installed [default: istio-system]."
return $?
}
management_restart () {
local CMD="$1";
CMD="${CMD:-help}"
cmd_exist "management_restart_$CMD" && {
"management_restart_${CMD}" "$@" && return $?
}
local RESTART_BROKER="$(config_get_option_flag_broker)"
local RESTART_BROKER_IMPL="$(config_get_option_flag_brokerimpl)"
local RESTART_CATALOG="$(config_get_option_flag_catalog)"
local RESTART_ISTIO="$(config_get_option_flag_istio)"
local RESTART_ALL="$(config_get_option_flag_all)"
local ISTIO_NAMESPACE="$(config_get_option_istio_namespace)"
info "Restarting Service Mesh component..."
if [ "$RESTART_BROKER" ] || [ "$RESTART_ALL" ]
then
management_restart_restart_broker
fi
if [ "$RESTART_BROKER_IMPL" ] || [ "$RESTART_ALL" ]
then
management_restart_restart_broker_impl
fi
if [ "$RESTART_CATALOG" ] || [ "$RESTART_ALL" ]
then
management_restart_restart_catalog
fi
if [ "$RESTART_ISTIO" ] || [ "$RESTART_ALL" ]
then
management_restart_restart_istio "$ISTIO_NAMESPACE"
fi
info "Done!"
return 0
}
management_restart_restart_broker () {
info "> Restarting service broker..."
kubectl -n service-mesh rollout restart deploy/service-mesh-incluster-broker 2> /dev/null
return $?
}
management_restart_restart_broker_impl () {
info "> Restarting service broker implementation..."
kubectl -n service-mesh rollout restart deploy/service-mesh-incluster-broker-impl 2> /dev/null
return $?
}
management_restart_restart_catalog () {
info "> Restarting service catalog..."
kubectl -n service-mesh rollout restart deploy/service-mesh-catalog-controller-manager 2> /dev/null
kubectl -n service-mesh rollout restart deploy/service-mesh-catalog-webhook 2> /dev/null
return $?
}
management_restart_restart_istio () {
info "> Restarting istio..."
local namespace="$1"
kubectl -n "$namespace" rollout restart deploy/istio-citadel 2> /dev/null
kubectl -n "$namespace" rollout restart deploy/istio-telemetry 2> /dev/null
kubectl -n "$namespace" rollout restart deploy/istio-sidecar-injector 2> /dev/null
kubectl -n "$namespace" rollout restart deploy/istio-policy 2> /dev/null
kubectl -n "$namespace" rollout restart deploy/istio-galley 2> /dev/null
kubectl -n "$namespace" rollout restart deploy/istio-pilot 2> /dev/null
kubectl -n "$namespace" rollout restart deploy/istiocoredns 2> /dev/null
kubectl -n "$namespace" rollout restart deploy/istiod 2> /dev/null
return $?
}
#!/bin/sh
# shellcheck disable=SC2039
api_binding_list () {
assert_servicemesh_is_installed
run_and_log kubectl get servicebindings --all-namespaces \
--selector 'service-mesh.mulesoft.com/kind=api-binding' \
--output 'custom-columns=NAMESPACE:.metadata.namespace,NAME:.metadata.name,ADAPTER:.spec.parameters.adapter,API:.spec.instanceRef.name,SERVICE NAME:.spec.parameters.service,STATUS:.status.conditions[?(@.type=="Ready")].reason' \
| utils_replace "InjectedBindResult" "Ready" | utils_replace "BindCallFailed" "Failed"
}
#!/bin/sh
# shellcheck disable=SC2039
management_check_sidecar () {
local NAMESPACE="$(config_get_option_namespace)"
info "Running sidecar check for namespace $NAMESPACE ..."
for podName in $(kubectl get pods -n "$NAMESPACE" -o name)
do
injected=$(kubectl -n "$NAMESPACE" describe "$podName" | grep -q istio-proxy: && echo "sidecar injected" || echo "sidecar NOT injected")
info "> $podName: $injected"
done
info "Done!"
return 0
}
#!/bin/sh
# shellcheck disable=SC2039
adapter_sizes () {
assert_servicemesh_is_installed
run_and_log kubectl get clusterserviceplans \
-o='custom-columns=NAME:.spec.externalName,CPU:.spec.externalMetadata.parameters.cpuLimit,MEMORY:.spec.externalMetadata.parameters.memoryLimit,DESCRIPTION:.spec.description' \
-l=servicecatalog.k8s.io/spec.clusterServiceClassRef.name=cd865c3f3777ab1bb44f1f9871ec7b17b27f4aafeb1629d524a9a92c # shasum -a 224
}
#!/bin/sh
# shellcheck disable=SC2039
adapter_binding_help () {
local CMD="$(basename $0) adapter binding"
info "Usage:"
info " $CMD list"
info " $CMD create --namespace=NAMESPACE --name=NAME --adapter=ADAPTER --apiId=API_ID --serviceName=SERVICE"
info " $CMD delete --namespace=NAMESPACE --name=NAME"
info " $CMD logs --namespace=NAMESPACE --name=NAME"
info ""
info "Options:"
info " --adapter=ADAPTER Name of the adapter."
info " --apiId=API_ID API ID from API Manager."
info " --name=NAME Service binding name."
info " --namespace=NAMESPACE Kubernetes Namespace."
info " --serviceName=SERVICE Kubernetes Service name."
info ""
info "Examples:"
info " # Create a new Service Binding"
info " $CMD create --namespace=nto-payment --name=customer --adapter=adapter --apiId=123456 --serviceName=customer-service"
info ""
info " # Show Service Binding logs"
info " $CMD logs --namespace=nto-payment --name=customer"
info ""
info " # Delete a Service Binding"
info " $CMD delete --namespace=nto-payment --name=customer"
info ""
info " # List all created Service Bindings"
info " $CMD list"
return $?
}
adapter_binding () {
local CMD="$1"; [ "$CMD" ] && shift;
CMD="${CMD:-help}"
cmd_exist "adapter_binding_$CMD" || {
error "Unknown command '${CMD}' for '$0 adapter binding'. Run '$0 adapter binding help' for usage."
return 1
}
"adapter_binding_${CMD}" "$@" || return $?
}
#!/bin/sh
## go
main "$@"
exit $?