diff options
Diffstat (limited to 'datarouter-prov-client/misc/drprov-client.sh')
-rwxr-xr-x | datarouter-prov-client/misc/drprov-client.sh | 286 |
1 files changed, 286 insertions, 0 deletions
diff --git a/datarouter-prov-client/misc/drprov-client.sh b/datarouter-prov-client/misc/drprov-client.sh new file mode 100755 index 00000000..71017954 --- /dev/null +++ b/datarouter-prov-client/misc/drprov-client.sh @@ -0,0 +1,286 @@ +#!/bin/sh + +PROVURL=${PROVURL:-"http://dmaap-dr-prov:8080"} +DRCONFIGDIR=${DRCONFIGDIR:-"/opt/app/config"} +ONBEHALFHDR="X-DMAAP-DR-ON-BEHALF-OF: drprovclient" +FEEDTYPE="Content-Type: application/vnd.dmaap-dr.feed" +SUBTYPE="Content-Type: application/vnd.dmaap-dr.subscription" +APPCONFIGINPUT=${APPCONFIGINPUT:-"/config-input"} +APPCONFIG=${APPCONFIG:-"/config"} + +function logit() { + # Direct log entries to stderr because to + # allow logging inside functions that use + # stdout to return values + echo $(date -u -Ins)\|"$@" >&2 +} + +function getFeedByNameVer() { +# Get feed info using name and version +# $1 -- Feed name (arbitrary string without embedded '"') +# $2 -- Feed version (arbitrary string without embedded '"') +# Returns feed data and exits with 0 if +# feed is found. +# Returns empty string and exits with 1 in +# any other case. + + # Construct urlencoded query + local NAME="$(printf %s "$1" | tr -d '"' | jq -R -r @uri)" + local VER="$(printf %s "$2" | tr -d '"' | jq -R -r @uri)" + local QUERYURL="${PROVURL}"/?"name=${NAME}"\&version="${VER}" + local FEEDDATA + + # Make the query + # Not checking exact cause for error, + # just looking for success or not. + local RV=1 + if FEEDDATA=$(curl --fail -s -H "${ONBEHALFHDR}" "${QUERYURL}") + then + echo ${FEEDDATA} + RV=0 + fi + + return ${RV} +} + +function subscriptionExists() { +# See if there a subscription to the feed +# that has the specified username, password, +# and delivery URL. +# $1 -- subscribe URL for the feed +# $2 -- username for the subscription +# $3 -- password for the subscription +# $4 -- delivery URL for the subscription +# Sets a return value of 0 if a matching +# subscription is found and echoes the +# corresponding subscription URL. +# Others sets a return value of 1 and +# echoes an empty string. + +local RV=1 +local SUBRESP +local SUBDATA +local SUBLIST + +# Query the feed's subscribe URL to get a +# list of the URLs for existing subscriptions +if SUBRESP=$(curl -s --fail -H "${ONBEHALFHDR}" "$1") +then + # Loop through the list of existing subscriptions + while read -r SUBURL # read from $SUBRESP (see redirect on "done") + do + # Retrieve subscription data from the subscription's URL + if SUBDATA=$(curl -s --fail -H "${ONBEHALFHDR}" "${SUBURL}") + then + local SUBUSER=$(echo ${SUBDATA} | jq -r .delivery.user) + local SUBPASS=$(echo ${SUBDATA} | jq -r .delivery.password) + local SUBDELURL=$(echo ${SUBDATA} | jq -r .delivery.url) + if [ "$2" = "${SUBUSER}" -a "$3" = "${SUBPASS}" -a "$4" = "${SUBDELURL}" ] + then + RV=0 #TRUE + break + fi + else + # This will happen, for instance, if the name in + # in the "X-DMAAP-DR-ON-BEHALF-OF" header doesn't + # match the owner of the feed. (Not likely in + # the ONAP use case, but possible.) Could also be + # the result of connectivity issues, bad URL,... + logit "WARNING: Could not retrieve ${SUBURL}" + fi + done < <(echo ${SUBRESP} | jq -r .[]) + else + logit "ERROR: failed to fetch subscription list from $1" +fi + +echo ${SUBURL} +return ${RV} +} + +function createFeedFromFile() { +# Create a feed using information from a JSON file +# Note that creating a feed also creates the publisher +# $1 -- Path to JSON file +# Returns feed data from the DR provisioning node +# and exits with 0 if the feed is created. +# Returns empty string and exits with 1 in +# any other case. + + local FEEDDATA + local RV=1 + + if test -f "$1" + then + # Substitute any environment variables in the subscription file + local FEEDREQUEST=$(envsubst < "$1") + if FEEDDATA=$(curl --fail -s --data-ascii "${FEEDREQUEST}" -H "${ONBEHALFHDR}" -H "$FEEDTYPE" ${PROVURL}/) + then + echo ${FEEDDATA} + RV=0 + fi + fi + +return ${RV} +} + +function createSubscriptionFromFile() { +# Create a subscription to a feed from a JSON file +# if a subscription with the same username, password +# and delivery URL doesn't already exist. +# We don't want multiple subscriptions if for some +# reason a subscriber's pod is redeployed. +# $1 -- JSON file defining the subscription +# + local SUBURL + local SUBDATA + local EXISTINGSUB + + local RV=1 + + if test -f "$1" + then + # Extract feed name and version from the JSON file + local FEEDNAME=$(jq '.feed.name' "$1") + local FEEDVER=$(jq '.feed.version' "$1") + + # Extract subscription parameters from the JSON file + # (needed for checking if there's an existing subscription) + local SUBUSER=$(jq -r '.delivery.user' "$1") + local SUBPASS=$(jq -r '.delivery.password' "$1") + local SUBDELURL=$(jq -r '.delivery.url' "$1") + + # Look up the feed and get the subscribe URL + if SUBURL=$(getFeedByNameVer "${FEEDNAME}" "${FEEDVER}" | jq -r .links.subscribe) + then + # Check whether a matching subscription already exists + if EXISTINGSUB=$(subscriptionExists ${SUBURL} ${SUBUSER} ${SUBPASS} ${SUBDELURL}) + then + logit "Using existing subscription: ${EXISTINGSUB}. No new subscription created." + RV=0 + else + # Substitute any environment variables in the subscription file + local SUBREQUEST=$(envsubst < "$1") + # Create the subscription + if SUBDATA=$(curl --fail -s --data-ascii "${SUBREQUEST}" -H "${ONBEHALFHDR}" -H "${SUBTYPE}" ${SUBURL}) + then + logit "Created new subscription: $(echo ${SUBDATA} | jq -r '.links.self')" + RV=0 + fi + fi + fi + fi + return ${RV} +} + +function createOrGetFeed() { +# Retrieve feed data from the DR provisioning node for +# the feed described in a JSON file. If the feed +# does not exist, create the file. +# $1 -- Path to JSON file +# Returns feed data from the DR provisioning node +# if the feed exists or if it has been successfully +# created, and exits with 0. +# Returns empty string and exits with 1 in +# any other case. + + local FEEDDATA + + local RV=1 + + if test -f "$1" + then + # Extract feed name and version from file + local NAME=$(cat "$1" | jq .name) + local VER=$(cat "$1" | jq .version) + + # Check whether feed already exists + # (DR does not allow two feeds with same name and version) + if FEEDDATA=$(getFeedByNameVer "${NAME}" "${VER}") + then + logit "Using existing feed: $(echo ${FEEDDATA} | jq -r '.links.self'). No new feed created." + RV=0 + else + # Create feed + if FEEDDATA=$(createFeedFromFile "$1") + then + logit "Created new feed: $(echo ${FEEDDATA} | jq -r '.links.self')" >&2 + RV=0 + fi + fi + fi + + echo ${FEEDDATA} + return $RV +} + +function provisionFeeds() { +# Create a feed for each JSON file in the +# directory specified in $1, unless the +# a feed with the same name and version +# already exists, in which case use the +# information for the existing feed. +# $1 -- Path to directory containing JSON +# files defining DR feeds + + local FEEDDATA + if test -d "$1" + then + for FEEDFILE in $(ls "$1"/*.json) + do + logit "Creating feed from ${FEEDFILE}" + if FEEDDATA=$(createOrGetFeed ${FEEDFILE}) + then + # Set environment variables with result data + # Note that FEEDNUM is taken from the number that's embedded + # in the file defining the feed. + FEEDNUM=$(echo "${FEEDFILE}" | sed 's/^.*\/.*-\([0-9]\+\).json/\1/') + export DR_FEED_PUBURL_${FEEDNUM}="$(echo ${FEEDDATA} | jq '.links.publish')" + export DR_FEED_LOGURL_${FEEDNUM}="$(echo ${FEEDDATA} | jq '.links.log')" + fi + done + fi +} + +function provisionSubscriptions() { +# Create a subscription for each JSON file in the +# directory specified in $1 +# $1 -- Path to directory containing JSON +# files definining DR subscriptions +# Note that when provisioning a subscription to a feed, +# the DR API doesn't return any additional information +# that the subscriber needs. Hence no information is +# extracted from the DR API response, and no environment +# variables are exported (unlike the provisionFeeds function.) + + if test -d "$1" + then + for SUBFILE in $(ls "$1"/*.json) + do + logit "Creating subscription from ${SUBFILE}" + createSubscriptionFromFile ${SUBFILE} + done + fi +} + +function updateConfigurations() { +# Run envsubst against each file in $1 (the application +# configuration input directory) to create a corresponding +# file in $2 (the application configuration directory) with +# environment variables replaced by the values set in the +# provisioning steps. The file(s) in $2 will be used by +# the application to get (among other things) the information +# needed to work with DR feeds. +# $1 -- path to application configuration input directory +# $2 -- path to application configuration directory + cd "$1" + for CONFFILE in $(ls -1) + do + logit "Substituting environment vars in ${CONFFILE}" + envsubst <${CONFFILE} > "$2"/${CONFFILE} + done +} +set -ue + +provisionFeeds ${DRCONFIGDIR}/feeds +provisionSubscriptions ${DRCONFIGDIR}/dr_subs +updateConfigurations ${APPCONFIGINPUT} ${APPCONFIG} |