Frost
Frost

Reputation: 159

ShellScript to send Mattermost notification is not working

I want to send a Message into a Mattermost channel with the help of a ShellScript/WebHook/cURL. The following code is the function to send the Message.

function matterSend() {
ENDPOINT=https://url.to.Mattermost/WebhookID
USERNAME="${USER}"
PAYLOAD=$(cat <<'EOF'
'payload={
"username" : "${USERNAME}",
"channel" : "TestChannel",
"text" : "#### Test to \n
| TestR     | TestS       | New Mode                               |
|:-----------|:-----------:|-----------------------------------------------:|
| ${2}       | ${3}        | ${1} :white_check_mark:            |
"
}'
EOF
)

  echo "CURL: curl -i -X POST -d ${PAYLOAD} ${ENDPOINT}"
  curl -i -X POST -d "${PAYLOAD}" "${ENDPOINT}"
}

As you can see, when I ECHO the command I get:

curl -i -X POST -d 'payload={
"username" : "TestUser",
"channel" : "TestChannel",
"text" : "#### Test to \n
| TestR     | TestS       | New Mode                               |
|:-----------|:-----------:|-----------------------------------------------:|
| ${2}       | ${3}        | ${1} :white_check_mark:            |
"
 }' https://url.to.Mattermost/WebhookID

If I paste that code directly into the terminal and execute it, it works. But when I run the script with the help of a Jenkins-Job I get the Error:

Unable to parse incoming data","message":"Unable to parse incoming data".

Why is it not working?

Upvotes: 2

Views: 2763

Answers (2)

Charles Duffy
Charles Duffy

Reputation: 295403

Generating JSON (or XML, or other structured formats) via string concatenation leads to pain and suffering. Instead, use a tool that actually understands the format.

Using a compliant generator such as jq means you no longer need to be responsible for putting \ns in the data (as multi-character strings), changing "s in text to \", or any of the other otherwise-necessary munging.

matterSend() {
  # Lowercase variable names; declare them local
  local endpoint=https://url.to.Mattermost/WebhookID
  local username=$USER
  local text="#### Test to
| TestR     | TestS       | New Mode                               |
|:-----------|:-----------:|-----------------------------------------------:|
| ${2}       | ${3}        | ${1} :white_check_mark:            |
"
  payload=$(jq --arg username "$username" \
               --arg channel "TestChannel" \
               --arg text "$text" \
               '{"username": $username, "channel": $channel, "text": $text}')

  # Advice: use "set -x" if you want to trace the commands your script would run.
  # ...or at least printf %q, as below; avoids misleading output from echo.
  # printf '%q ' curl -i -X POST -d "$payload" "$endpoint" >&2; echo >&2
  curl -i -X POST -d "$payload" "$endpoint"
}

Upvotes: 1

tripleee
tripleee

Reputation: 189387

Without knowledge of the API you are connecting to, I would guess that you need

# Drop function keyword, indent body
matterSend() {
  # Lowercase variable names; declare them local
  local endpoint=https://url.to.Mattermost/WebhookID
  local username=$USER
  # Pro tip: don't use a variable for the payload if it's effectively static
  payload=$(cat <<-__EOF
    payload={
    "username" : "$username",
    "channel" : "TestChannel",
    "text" : "#### Test to \\n| TestR     | TestS       | New Mode                               |\\n|:-----------|:-----------:|-----------------------------------------------:|\\n| ${2}       | ${3}        | ${1} :white_check_mark:            |\\n"
    }
__EOF
  )

  echo "CURL: curl -i -X POST -d $payload $endpoint"
  curl -i -X POST -d "$payload" "$endpoint"
}

Replacing the newlines inside the "text" element with \n (and doubling the backslash because the here document is now being interpreted by the shell when it's assigned) is mildly speculative; perhaps remove the remaining newlines, too. The real beef is removing the misplaced literal single quotes around the payload.

Maybe also explore printf for formatting fixed-width tabular text.

The here document's <<-__EOF uses the unquoted separator __EOF and the dash before it says to remove any tabs from the beginning of each line. Needless to say, the indentation on those lines consists of a literal tab character.

Upvotes: 1

Related Questions