Tutorial05 done

This commit is contained in:
Roberto Abdelkader Martínez Pérez
2019-11-26 17:58:58 +01:00
parent 21e77c9685
commit 69eb0eed3b
+229
View File
@@ -0,0 +1,229 @@
Sharing the Stats
=================
**Junior**
Good morning!
**Senior**
Just about time... We are in trouble!
The report stuff was a complete success, so much that now *Susan* has
hired a frontend developer to create a custom dashboard to see the
stats in real time.
Now we have to provide the backend for the solution.
**Junior**
And whats the problem?
**Senior**
We are not developers what are we doing writing backend?
**Junior**
Chill out, man. Can't be that difficult? What they need exactly?
**Senior**
We have to provide a new endpoint to serve the same data but in JSON
format.
**Junior**
So we have half of the work already done.
What about this?
.. code-block:: bash
kapow route add /capacitystats - <<-HERE
echo "{\"memory\": \"`free -m`\"}" | kapow set /response/body
HERE
**Senior**
For starters that's not valid JSON. The output would be something
like:
.. code-block:: console
$ echo "{\"memory\": \"`free -m`\"}"
{"memory": " total used free shared buff/cache available
Mem: 31967 3121 21680 980 7166 27418
Swap: 0 0 0"}
You can't add new lines inside a JSON string that way, you have to
encode with ``\n``.
**Junior**
Are you sure?
**Senior**
See it by yourself.
.. code-block:: console
$ echo "{\"memory\": \"`free -m`\"}" | jq
parse error: Invalid string: control characters from U+0000 through U+001F must be escaped at line 3, column 44
**Junior**
``jq``? What is that command?
**Senior**
``jq`` is a wonderful tool for working with JSON data from the command
line. With you ``jq`` you can extract data from JSON and also
generate well-formed JSON.
**Junior**
Let's use it then!
How can we generate a JSON document with ``jq``?
**Senior**
To generate a document we use the ``-n`` argument:
.. code-block:: console
$ jq -n '{"mykey": "myvalue"}'
{
"mykey": "myvalue"
}
**Junior**
That is not very useful. The output is the same.
**Senior**
It get's better. You can add variables to the JSON and ``jq`` will escape them for you.
.. code-block:: console
$ jq -n --arg myvar "$(echo -n myvalue)" '{"mykey": $myvar}'
{
"mykey": "myvalue"
}
**Junior**
That's just what I need.
What do you think of this?
.. code-block:: console
$ jq -n --arg host "$(hostname)" --arg date "$(date)" --arg memory "$(free -m)" --arg load "$(uptime)" --arg disk "$(df -h)" '{"hostname": $host, "date": $date, "memory": $memory, "load": $load, "disk": $disk}'
{
"hostname": "junior-host",
"date": "Tue 26 Nov 2019 05:27:24 PM CET",
"memory": " total used free shared buff/cache available\nMem: 31967 3114 21744 913 7109 27492\nSwap: 0 0 0",
"load": " 17:27:24 up 10:21, 1 user, load average: 0.20, 0.26, 0.27",
"disk": "Filesystem Size Used Avail Use% Mounted on\ndev 16G 0 16G 0% /dev"
}
**Senior**
That is the data we have to produce. But the code is far from readable. And
you also forgot about adding the endpoint.
Can we do any better?
**Junior**
That's easy:
.. code-block:: bash
kapow route add /capacitystats - <<-HERE
jq -n \
--arg hostname "$(hostname)" \
--arg date "$(date)" \
--arg memory "$(free -m)" \
--arg load "$(uptime)" \
--arg disk "$(df -h)" \
'{"hostname": $hostname, "date": $date, "memory": $memory, "load": $load, "disk": $disk}' \
| kapow set /response/body
HERE
What do you think?
**Senior**
You forgot one more thing.
**Junior**
I think you are wrong, the JSON is well-formed and it contains all the
required data. Also the code is very readable.
**Senior**
You are right but, you are not using HTTP correctly. You have to set the
``Content-Type`` header to let your client know the format of the data you are
outputting.
**Junior**
Ok, let me try:
.. code-block:: bash
kapow route add /capacitystats - <<-HERE
jq -n \
--arg hostname "$(hostname)" \
--arg date "$(date)" \
--arg memory "$(free -m)" \
--arg load "$(uptime)" \
--arg disk "$(df -h)" \
'{"hostname": $hostname, "date": $date, "memory": $memory, "load": $load, "disk": $disk}' \
| kapow set /response/body
echo application/json | kapow set /response/headers/Content-Type
HERE
**Senior**
Just a couple of details.
1. You have to set the headers **before** the body. This is because the body
can be so big that Kapow! is forced to start sending it out.
2. In cases where you want to set a small piece of data (like the header) is
better to not use the ``stdin``. Kapow! provides a secondary syntax for these
cases:
.. code-block:: console
$ kapow set <resource> <value>
**Junior**
Something like this?
.. code-block:: bash
kapow route add /capacitystats - <<-HERE
kapow set /response/headers/Content-Type application/json
jq -n \
--arg hostname "$(hostname)" \
--arg date "$(date)" \
--arg memory "$(free -m)" \
--arg load "$(uptime)" \
--arg disk "$(df -h)" \
'{"hostname": $hostname, "date": $date, "memory": $memory, "load": $load, "disk": $disk}' \
| kapow set /response/body
HERE
**Senior**
That's perfect! Let's upload this to the *Corporate Server* and tell the
frontend developer.