how to use loop with some conditions in shell script - linux

I need to run a curl command several times, and check the result every time. I used a for loop to check the output from curl, and I want to exit the loop when the correct status is reached.
The very first time the curl command is run, it will show me this output :
{
"name": "organizations/org_name/operations/long_running_operation_ID",
"metadata": {
"#type": "type.googleapis.com/google.cloud.apigee.v1.OperationMetadata",
"operationType": "INSERT",
"targetResourceName": "organizations/org_name",
"state": "IN_PROGRESS"
}
}
It takes time to complete, that's why it says IN_PROGRESS. It took around 30 to 60 sec, and if we run the same curl command after 30 to 60 sec then it will show the output below :
{
"error": {
"code": 409,
"message": "org graceful-path-310004 already associated with another project",
"status": "ALREADY_EXISTS",
"details": [
{
"#type": "type.googleapis.com/google.rpc.RequestInfo",
"requestId": "11430211642328568827"
}
]
}
}
Here is the script I have so far :
test=$(curl -H "Authorization: Bearer $TOKEN" -X POST -H "content-type:application/json" \
-d '{
"name":"'"$ORG_NAME"'",
"displayName":"'"$ORG_DISPLAY_NAME"'",
"description":"'"$ORGANIZATION_DESCRIPTION"'",
"runtimeType":"'"$RUNTIMETYPE"'",
"analyticsRegion":"'"$ANALYTICS_REGION"'"
}' \
"https://apigee.googleapis.com/v1/organizations?parent=projects/$PROJECT_ID" | jq '.error.status')
echo $test
while [ $test = "ALREADY EXISTS" || $test != "IN_PROGRESS" ]
do
echo $test
echo "Organization is creating"
test=$(curl -H "Authorization: Bearer $TOKEN" -X POST -H "content-type:application/json" \
-d '{
"name":"'"$ORG_NAME"'",
"displayName":"'"$ORG_DISPLAY_NAME"'",
"description":"'"$ORGANIZATION_DESCRIPTION"'",
"runtimeType":"'"$RUNTIMETYPE"'",
"analyticsRegion":"'"$ANALYTICS_REGION"'"
}' \
"https://apigee.googleapis.com/v1/organizations?parent=projects/$PROJECT_ID" | jq '.error.status')
done
echo "exit from loop"

To reduce the duplicated code, use functions.
Also, best practice to use jq to generate json -- it will safely handle any embedded quotes in the data:
json() {
jq --arg name "$ORG_NAME" \
--arg displayName "$ORG_DISPLAY_NAME" \
--arg description "$ORGANIZATION_DESCRIPTION" \
--arg runtimeType "$RUNTIMETYPE" \
--arg analyticsRegion "$ANALYTICS_REGION" \
--null-input --compact-output \
'$ARGS.named'
}
errorStatus() {
curl -H "Authorization: Bearer $TOKEN" \
-X POST \
-H "content-type:application/json" \
-d "$(json)" \
"${URL}?parent=projects/$PROJECT_ID" \
| jq -r '.error.status'
}
while true; do
status=$(errorStatus)
[ "$status" = "ALREADY EXISTS" ] && break
done
echo "exit from loop"
The while true; do some code; condition && break; done bit is the bash version of a do-while loop

Related

How to store only one response of curl command [duplicate]

This question already has answers here:
Difference between single and double quotes in Bash
(7 answers)
Closed 1 year ago.
i want to store the output of curl command in a variable but not whole response only one value of that response
i have this curl command
curl -H "Authorization: Bearer $TOKEN" -X POST -H "content-type:application/json" \
-d '{
"name":"'"$ORG_NAME"'",
"displayName":"'"$ORG_DISPLAY_NAME"'",
"description":"'"$ORGANIZATION_DESCRIPTION"'",
"runtimeType":"'"$RUNTIMETYPE"'",
"analyticsRegion":"'"$ANALYTICS_REGION"'"
}' \
"https://apigee.googleapis.com/v1/organizations?parent=projects/$PROJECT_ID"
when i hit this command then it will show the response look like this
{
"name": "organizations/heloo/operations/keijfiejwfefekd",
"metadata": {
"#type": "type.googleapis.com/google.cloud.apigee.v1.OperationMetadata",
"operationType": "INSERT",
"targetResourceName": "organizations/heloo",
"state": "IN_PROGRESS"
}
}
so in the response i want to store this state value in a variable
test=$(curl -H "Authorization: Bearer $TOKEN" -X POST -H "content-type:application/json" \
-d '{
"name":"'"$ORG_NAME"'",
"displayName":"'"$ORG_DISPLAY_NAME"'",
"description":"'"$ORGANIZATION_DESCRIPTION"'",
"runtimeType":"'"$RUNTIMETYPE"'",
"analyticsRegion":"'"$ANALYTICS_REGION"'"
}' \
"https://apigee.googleapis.com/v1/organizations?parent=projects/$PROJECT_ID" | jq '.metadata.state')
it will work

bash script error while sending data to api

Below is my bash script:
#!/bin/bash
message=$1
hostname=$2
appname=$3
severity=$4
data='{"action":"EventsRouter","method":"add_event","data":[{"summary":"'$message'","device":"'$hostname'","message":"message","component":"'$appname'","severity":"'$severity'","evclasskey":"nxlog","evclass":"nxlog","monitor":"localhost"}],"type":"rpc","tid":2}'
echo "Total number of args : $#"
echo "message = $message"
echo "hostname = $hostname"
echo "appname = $appname"
echo "data = $data"
curl -u "Eve:Welcome666" -k "https://myurlcom/zport/dmd/evconsole_router" -d $data -H "Content-Type:application/json"
and my error is:
Total number of args : 4
message = mes
hostname = hos
appname = sev
data = {"action":"EventsRouter","method":"add_event","data":[{"summary":"mes","device":"hos","message":"message","component":"sev","severity":"ap","evclasskey":"nxlog","evclass":"nxlog","monitor":"localhost"}],"type":"rpc","tid":2}
{"uuid": "9b66e70d-44fc-463d-a347-786fe5502c13", "action": "EventsRouter", "result": {"msg": "Failed to create event: NoRouteException: Reply code: 312, Reply text: NO_ROUTE, Exchange:zenoss.zenevents.raw, Routing key: zenoss.zeneventnxlog", "type":"exception", "success": false}, "tid": 2, "type": "rpc", "method": "add_event"}
However, when i curl a data directly, it is working.
curl -u Eve:Welcome666 -k https://myurl.com/zport/dmd/evconsole_router -d '{"action":"EventsRouter", "method":"add_event","data":[{"summary":"test","device":"test","message":"msg","component":"testhost","severity":"5", "evclasskey":"nxlog", "evclass":"/nxlog/perf","monitor":"localhost"}],"type":"rpc","tid":2}' -H "Content-Type:application/json"
{"uuid": "1654584c-5f86-489e-a5e7-35d45e462066", "action": "EventsRouter", "result": {"msg": "Created event", "success": true},"tid": 2, "type": "rpc", "method": "add_event"}
I think you are missing quotes around $data in the script, the correct form is:
curl -u "Eve:Welcome666" -k "https://myurlcom/zport/dmd/evconsole_router" -d "'$data'" -H "Content-Type:application/json"

escape variable in bash script curl request

I am trying to curl via bash script but unable to pass the value of var1 in curl request and getting error upon execution ...
#!/bin/bash
var1="some test message"
curl 'https://link' \
-H 'Content-Type: application/json' \
-d '
{"msgtype": "text",
"text": {
"content": $var1
}
}'
Your variable $var1 doesn't get expanded by the shell because it is inside single quote '.
You need to use double quote to let bash do the parameter expansion, and escape your json data:
#!/bin/bash
var1="some test message"
curl 'https://link' \
-H 'Content-Type: application/json' \
-d "
{
\"msgtype\": \"text\",
\"text\": {
\"content\": \"$var1\"
}
}"
Or you can use inline document (without the escaping hell, but the command becomes awkward):
#!/bin/bash
var1="some test message"
curl 'https://link' \
-H 'Content-Type: application/json' \
-d "$(cat <<EOT
{
"msgtype": "text",
"text": {
"content": "$var1"
}
}
EOT
)"
In general, don't use parameter expansion to define JSON dynamically like this. There is no guarantee that your template, combined with the contents of the variable, produces well-formed JSON. (This is for the same reasons you don't use string interpolation to create dynamic SQL queries.) Use a tool like jq instead.
curl 'https://link' ... \
-d "$(jq --argjson x "$var" \
-n '{msgtype: "text", text: {content: $x}}')"
Use below script.
https://aaa.com' -H 'Content-Type: application/json' -d '{"msgtype": "text", "text": { "content": '"'$var1'"' }}'

Dialogflow v2 REST call returns 400 Bad Request

I get a 400 Bad Request when issuing this entityTypes.create call:
wget --header="Authorization: Bearer ${TOKEN}" \
--post-data=' { "displayName": "writer1", "kind": "KIND_MAP", "autoExpansionMode": "AUTO_EXPANSION_MODE_DEFAULT", "entities": [ { "value": "Virginia Woolf", "synonyms": [ "Virginia Woolf" ] } }' \
https://dialogflow.googleapis.com/v2/projects/MyProject/agent/entityTypes
but this -- entityTypes.list -- works OK:
wget --header="Authorization: Bearer ${TOKEN}" \
https://dialogflow.googleapis.com/v2/projects/MyProject/agent/entityTypes
Any ideas? Thanks.
By default, --post-data uses a content-type of application/x-www-form-urlencoded. The API requires the content-type of application/json.
I tend to use something more like
wget \
--header="Authorization: Bearer ${TOKEN}" \
--header="Content-type: application/json" \
--post-data='{ ... }' \
https://dialogflow.googleapis.com/v2/projects/MyProject/agent/entityTypes

How to read headers from file using cURL?

I found this.
And I wrote this variant:
#!/bin/bash
while read line ; do
headers="$headers -H '$line'"
done < public/headers.txt
echo $headers
curl -X PUT \
$headers \
-d #'public/example.json' \
echo.httpkit.com
In headers.txt I have:
X-PAYPAL-SECURITY-USERID:123
X-PAYPAL-SECURITY-PASSWORD:123
But when I run ./public/curl.sh I am not getting the headers I am sending.
I isolated the issue with an env var:
$ x='-H some:asd'
$ curl $x echo.httpkit.com
=> header was NOT present
$ curl -H 'some:asd' echo.httpkit.com
=> header was present
$ curl -H some:asd echo.httpkit.com
=> header was present
How can I correctly insert a variable in the header section?
Let's ask shellcheck:
In yourscript line 3:
headers="$headers -H '$line'"
^-- SC2089: Quotes/backslashes will be treated literally.
Use an array.
Ok, then let's do that:
#!/bin/bash
while read line ; do
headers=("${headers[#]}" -H "$line")
done < public/headers.txt
echo "${headers[#]}"
curl -X PUT \
"${headers[#]}" \
-d #'public/example.json' \
echo.httpkit.com
Result:
{
"method": "PUT",
"uri": "/",
"path": {
"name": "/",
"query": "",
"params": {}
},
"headers": {
"host": "echo.httpkit.com",
"user-agent": "curl/7.35.0",
"accept": "*/*",
"x-paypal-security-userid": "123", // <----- Yay!!
"x-paypal-security-password": "123",
"content-length": "32",
"content-type": "application/x-www-form-urlencoded"
},
"body": "\"This is text from example.json\"",
"ip": "127.0.0.1",
"powered-by": "http://httpkit.com",
"docs": "http://httpkit.com/echo"
}
If you don't want to put the HTTP headers on a command line (perhaps for security reasons), you can still have curl read them directly from a file.
curl -H #headerfile.txt https://www.google.com/ # requires curl >=7.55.0
If your curl is older than 7.55.0:
Use the option -K/--config <config file>, and put several -H/--header <header> lines in the text file.
For more details, please see my answer in the original article:
https://stackoverflow.com/a/48762561/5201675

Resources