update link to upper-constraints.txt
[dmaap/datarouter.git] / datarouter-prov-client / misc / drprov-client.sh
1 #!/bin/sh
2 #
3 # ============LICENSE_START===============================================
4 # org.onap.dmaap
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
11 #
12 #        http://www.apache.org/licenses/LICENSE-2.0
13 #
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=================================================
20
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"}
28
29 function logit() {
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
34 }
35
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
41 #   feed is found.
42 #   Returns empty string and exits with 1 in
43 #   any other case.
44
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}"
49     local FEEDDATA
50
51     # Make the query
52     # Not checking exact cause for error,
53     # just looking for success or not.
54     local RV=1
55     if FEEDDATA=$(curl --fail -s -H "${ONBEHALFHDR}" "${QUERYURL}")
56     then
57             echo ${FEEDDATA}
58         RV=0
59     fi
60
61     return ${RV}
62 }
63
64 function subscriptionExists() {
65 #  See if there a subscription to the feed
66 #  that has the specified username, password,
67 #  and delivery URL.
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.
77
78 local RV=1
79 local SUBRESP
80 local SUBDATA
81 local SUBLIST
82
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")
86 then
87     # Loop through the list of existing subscriptions
88     while read -r SUBURL   # read from $SUBRESP (see redirect on "done")
89     do
90         # Retrieve subscription data from the subscription's URL
91         if SUBDATA=$(curl -s --fail -H "${ONBEHALFHDR}" "${SUBURL}")
92         then
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}" ]
97             then
98                 RV=0  #TRUE
99                 break
100             fi
101         else
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}"
108         fi
109     done < <(echo ${SUBRESP} | jq -r .[])
110  else
111     logit "ERROR: failed to fetch subscription list from $1"
112 fi
113
114 echo ${SUBURL}
115 return ${RV}
116 }
117
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
125 #   any other case.
126
127     local FEEDDATA
128     local RV=1
129
130     if test -f "$1"
131     then
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}/)
135         then
136             echo ${FEEDDATA}
137             RV=0
138         fi
139     fi
140
141 return ${RV}
142 }
143
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
151 #
152     local SUBURL
153     local SUBDATA
154     local EXISTINGSUB
155
156     local RV=1
157
158     if test -f "$1"
159     then
160         # Extract feed name and version from the JSON file
161         local FEEDNAME=$(jq '.feed.name' "$1")
162         local FEEDVER=$(jq '.feed.version' "$1")
163
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")
169
170         # Look up the feed and get the subscribe URL
171         if SUBURL=$(getFeedByNameVer "${FEEDNAME}" "${FEEDVER}" | jq -r .links.subscribe)
172         then
173             # Check whether a matching subscription already exists
174             if EXISTINGSUB=$(subscriptionExists ${SUBURL} ${SUBUSER} ${SUBPASS} ${SUBDELURL})
175             then
176                 logit "Using existing subscription: ${EXISTINGSUB}.  No new subscription created."
177                 RV=0
178             else
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})
183                 then
184                     logit "Created new subscription: $(echo ${SUBDATA} | jq -r '.links.self')"
185                     RV=0
186                 fi
187             fi
188         fi
189     fi
190     return ${RV}
191 }
192
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
202 #  any other case.
203
204     local FEEDDATA
205
206     local RV=1
207
208     if test -f "$1"
209     then
210         # Extract feed name and version from file
211         local NAME=$(cat "$1" | jq .name)
212         local VER=$(cat "$1" | jq .version)
213
214         # Check whether feed already exists
215         # (DR does not allow two feeds with same name and version)
216         if FEEDDATA=$(getFeedByNameVer "${NAME}" "${VER}")
217         then
218             logit "Using existing feed: $(echo ${FEEDDATA} | jq -r '.links.self'). No new feed created."
219             RV=0
220         else
221             # Create feed
222             if FEEDDATA=$(createFeedFromFile "$1")
223             then
224                 logit "Created new feed:  $(echo ${FEEDDATA} | jq -r '.links.self')" >&2
225                 RV=0
226             fi
227         fi
228     fi
229
230     echo ${FEEDDATA}
231     return $RV
232 }
233
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
242
243     local FEEDDATA
244     if test -d "$1"
245     then
246         for FEEDFILE in $(ls "$1"/*.json)
247         do
248             logit "Creating feed from ${FEEDFILE}"
249             if FEEDDATA=$(createOrGetFeed ${FEEDFILE})
250             then
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')"
257             fi
258         done
259     fi
260 }
261
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.)
272
273     if test -d "$1"
274     then
275         for SUBFILE in $(ls "$1"/*.json)
276         do
277             logit "Creating subscription from ${SUBFILE}"
278             createSubscriptionFromFile ${SUBFILE}
279         done
280     fi
281 }
282
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
293     cd "$1"
294     for CONFFILE in $(ls -1)
295     do
296         logit "Substituting environment vars in ${CONFFILE}"
297         envsubst <${CONFFILE} > "$2"/${CONFFILE}
298     done
299 }
300 set -ue
301
302 provisionFeeds ${DRCONFIGDIR}/feeds
303 provisionSubscriptions ${DRCONFIGDIR}/dr_subs
304 updateConfigurations ${APPCONFIGINPUT} ${APPCONFIG}