3 # ============LICENSE_START===============================================
5 # ========================================================================
6 # Copyright (c) J. F. Lucas. All rights reserved.
7 # # ========================================================================
8 # Licensed under the Apache License, Version 2.0 (the "License");
9 # you may not use this file except in compliance with the License.
10 # You may obtain a copy of the License at
12 # http://www.apache.org/licenses/LICENSE-2.0
14 # Unless required by applicable law or agreed to in writing, software
15 # distributed under the License is distributed on an "AS IS" BASIS,
16 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 # See the License for the specific language governing permissions and
18 # limitations under the License.
19 # ============LICENSE_END=================================================
21 PROVURL=${PROVURL:-"http://dmaap-dr-prov:8080"}
22 DRCONFIGDIR=${DRCONFIGDIR:-"/opt/app/config"}
23 ONBEHALFHDR="X-DMAAP-DR-ON-BEHALF-OF: drprovcl"
24 FEEDTYPE="Content-Type: application/vnd.dmaap-dr.feed"
25 SUBTYPE="Content-Type: application/vnd.dmaap-dr.subscription"
26 APPCONFIGINPUT=${APPCONFIGINPUT:-"/config-input"}
27 APPCONFIG=${APPCONFIG:-"/config"}
30 # Direct log entries to stderr because to
31 # allow logging inside functions that use
32 # stdout to return values
33 echo $(date -u -Ins)\|"$@" >&2
36 function getFeedByNameVer() {
37 # Get feed info using name and version
38 # $1 -- Feed name (arbitrary string without embedded '"')
39 # $2 -- Feed version (arbitrary string without embedded '"')
40 # Returns feed data and exits with 0 if
42 # Returns empty string and exits with 1 in
45 # Construct urlencoded query
46 local NAME="$(printf %s "$1" | tr -d '"' | jq -R -r @uri)"
47 local VER="$(printf %s "$2" | tr -d '"' | jq -R -r @uri)"
48 local QUERYURL="${PROVURL}"/?"name=${NAME}"\&version="${VER}"
52 # Not checking exact cause for error,
53 # just looking for success or not.
55 if FEEDDATA=$(curl --fail -s -H "${ONBEHALFHDR}" "${QUERYURL}")
64 function subscriptionExists() {
65 # See if there a subscription to the feed
66 # that has the specified username, password,
68 # $1 -- subscribe URL for the feed
69 # $2 -- username for the subscription
70 # $3 -- password for the subscription
71 # $4 -- delivery URL for the subscription
72 # Sets a return value of 0 if a matching
73 # subscription is found and echoes the
74 # corresponding subscription URL.
75 # Others sets a return value of 1 and
76 # echoes an empty string.
83 # Query the feed's subscribe URL to get a
84 # list of the URLs for existing subscriptions
85 if SUBRESP=$(curl -s --fail -H "${ONBEHALFHDR}" "$1")
87 # Loop through the list of existing subscriptions
88 while read -r SUBURL # read from $SUBRESP (see redirect on "done")
90 # Retrieve subscription data from the subscription's URL
91 if SUBDATA=$(curl -s --fail -H "${ONBEHALFHDR}" "${SUBURL}")
93 local SUBUSER=$(echo ${SUBDATA} | jq -r .delivery.user)
94 local SUBPASS=$(echo ${SUBDATA} | jq -r .delivery.password)
95 local SUBDELURL=$(echo ${SUBDATA} | jq -r .delivery.url)
96 if [ "$2" = "${SUBUSER}" -a "$3" = "${SUBPASS}" -a "$4" = "${SUBDELURL}" ]
102 # This will happen, for instance, if the name in
103 # in the "X-DMAAP-DR-ON-BEHALF-OF" header doesn't
104 # match the owner of the feed. (Not likely in
105 # the ONAP use case, but possible.) Could also be
106 # the result of connectivity issues, bad URL,...
107 logit "WARNING: Could not retrieve ${SUBURL}"
109 done < <(echo ${SUBRESP} | jq -r .[])
111 logit "ERROR: failed to fetch subscription list from $1"
118 function createFeedFromFile() {
119 # Create a feed using information from a JSON file
120 # Note that creating a feed also creates the publisher
121 # $1 -- Path to JSON file
122 # Returns feed data from the DR provisioning node
123 # and exits with 0 if the feed is created.
124 # Returns empty string and exits with 1 in
132 # Substitute any environment variables in the subscription file
133 local FEEDREQUEST=$(envsubst < "$1")
134 if FEEDDATA=$(curl --fail -s --data-ascii "${FEEDREQUEST}" -H "${ONBEHALFHDR}" -H "$FEEDTYPE" ${PROVURL}/)
144 function createSubscriptionFromFile() {
145 # Create a subscription to a feed from a JSON file
146 # if a subscription with the same username, password
147 # and delivery URL doesn't already exist.
148 # We don't want multiple subscriptions if for some
149 # reason a subscriber's pod is redeployed.
150 # $1 -- JSON file defining the subscription
160 # Extract feed name and version from the JSON file
161 local FEEDNAME=$(jq '.feed.name' "$1")
162 local FEEDVER=$(jq '.feed.version' "$1")
164 # Extract subscription parameters from the JSON file
165 # (needed for checking if there's an existing subscription)
166 local SUBUSER=$(jq -r '.delivery.user' "$1")
167 local SUBPASS=$(jq -r '.delivery.password' "$1")
168 local SUBDELURL=$(jq -r '.delivery.url' "$1")
170 # Look up the feed and get the subscribe URL
171 if SUBURL=$(getFeedByNameVer "${FEEDNAME}" "${FEEDVER}" | jq -r .links.subscribe)
173 # Check whether a matching subscription already exists
174 if EXISTINGSUB=$(subscriptionExists ${SUBURL} ${SUBUSER} ${SUBPASS} ${SUBDELURL})
176 logit "Using existing subscription: ${EXISTINGSUB}. No new subscription created."
179 # Substitute any environment variables in the subscription file
180 local SUBREQUEST=$(envsubst < "$1")
181 # Create the subscription
182 if SUBDATA=$(curl --fail -s --data-ascii "${SUBREQUEST}" -H "${ONBEHALFHDR}" -H "${SUBTYPE}" ${SUBURL})
184 logit "Created new subscription: $(echo ${SUBDATA} | jq -r '.links.self')"
193 function createOrGetFeed() {
194 # Retrieve feed data from the DR provisioning node for
195 # the feed described in a JSON file. If the feed
196 # does not exist, create the file.
197 # $1 -- Path to JSON file
198 # Returns feed data from the DR provisioning node
199 # if the feed exists or if it has been successfully
200 # created, and exits with 0.
201 # Returns empty string and exits with 1 in
210 # Extract feed name and version from file
211 local NAME=$(cat "$1" | jq .name)
212 local VER=$(cat "$1" | jq .version)
214 # Check whether feed already exists
215 # (DR does not allow two feeds with same name and version)
216 if FEEDDATA=$(getFeedByNameVer "${NAME}" "${VER}")
218 logit "Using existing feed: $(echo ${FEEDDATA} | jq -r '.links.self'). No new feed created."
222 if FEEDDATA=$(createFeedFromFile "$1")
224 logit "Created new feed: $(echo ${FEEDDATA} | jq -r '.links.self')" >&2
234 function provisionFeeds() {
235 # Create a feed for each JSON file in the
236 # directory specified in $1, unless the
237 # a feed with the same name and version
238 # already exists, in which case use the
239 # information for the existing feed.
240 # $1 -- Path to directory containing JSON
241 # files defining DR feeds
246 for FEEDFILE in $(ls "$1"/*.json)
248 logit "Creating feed from ${FEEDFILE}"
249 if FEEDDATA=$(createOrGetFeed ${FEEDFILE})
251 # Set environment variables with result data
252 # Note that FEEDNUM is taken from the number that's embedded
253 # in the file defining the feed.
254 FEEDNUM=$(echo "${FEEDFILE}" | sed 's/^.*\/.*-\([0-9]\+\).json/\1/')
255 export DR_FEED_PUBURL_${FEEDNUM}="$(echo ${FEEDDATA} | jq '.links.publish')"
256 export DR_FEED_LOGURL_${FEEDNUM}="$(echo ${FEEDDATA} | jq '.links.log')"
262 function provisionSubscriptions() {
263 # Create a subscription for each JSON file in the
264 # directory specified in $1
265 # $1 -- Path to directory containing JSON
266 # files definining DR subscriptions
267 # Note that when provisioning a subscription to a feed,
268 # the DR API doesn't return any additional information
269 # that the subscriber needs. Hence no information is
270 # extracted from the DR API response, and no environment
271 # variables are exported (unlike the provisionFeeds function.)
275 for SUBFILE in $(ls "$1"/*.json)
277 logit "Creating subscription from ${SUBFILE}"
278 createSubscriptionFromFile ${SUBFILE}
283 function updateConfigurations() {
284 # Run envsubst against each file in $1 (the application
285 # configuration input directory) to create a corresponding
286 # file in $2 (the application configuration directory) with
287 # environment variables replaced by the values set in the
288 # provisioning steps. The file(s) in $2 will be used by
289 # the application to get (among other things) the information
290 # needed to work with DR feeds.
291 # $1 -- path to application configuration input directory
292 # $2 -- path to application configuration directory
294 for CONFFILE in $(ls -1)
296 logit "Substituting environment vars in ${CONFFILE}"
297 envsubst <${CONFFILE} > "$2"/${CONFFILE}
302 provisionFeeds ${DRCONFIGDIR}/feeds
303 provisionSubscriptions ${DRCONFIGDIR}/dr_subs
304 updateConfigurations ${APPCONFIGINPUT} ${APPCONFIG}