Formatting and filtering OCI CLI output

The default output format of the OCI commandline interface is JSON. Every available piece of information is included in the response. Especially when you use it in Shell scripts or applications, it can be difficult to extract the desired information.

This blog post demonstrate the build-in filtering capabilities and the available output formats.

Formatting

Currently two different output formats are supported by the OCI CLI.

  • JSON (default)
  • Table-formatted

To override the default output format, the parameter –output is used.

Error messages are always returned as JSON response, despite what output format is set.

$> oci os object list -bn non-existing-bucket --output table
ServiceError:
{
    "code": "BucketNotFound",
    "message": "Either the bucket named 'non-existing-bucket' does not exist in the namespace 'xxxxxxxxxxxx' or you are not authorized to access it",
    "opc-request-id": "fra-1:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    "status": 404
}

JSON

$> oci os object list -bn "my-bucket-210121-1425" --output json

{
  "data": [
    {
      "archival-state": null,
      "etag": "e0030182-3850-4e52-9ef8-567c794b63b8",
      "md5": "H8scWcchoH1XrSuTgTTehA==",
      "name": "expdp.par",
      "size": 193,
      "storage-tier": "Standard",
      "time-created": "2021-02-18T13:09:02.178000+00:00",
      "time-modified": "2021-03-05T15:03:21.412000+00:00"
    },
    {
      "archival-state": null,
      "etag": "647876cf-dd32-4d07-8a75-6e5fb2b8a0de",
      "md5": "Fd3Oqm702wD8TQqt3odybw==",
      "name": "expdp2.par",
      "size": 145,
      "storage-tier": "Standard",
      "time-created": "2021-02-18T12:14:47.533000+00:00",
      "time-modified": "2021-02-18T12:14:47.620000+00:00"
    }
  ],
  "prefixes": []
}

The JSON response is already formatted in a human-readable format.

Table-formatted

$> oci os object list -bn "my-bucket-210121-1425" --output table

+----------------+--------------------------------------+--------------------------+--------------------+--------+--------------+----------------------------------+----------------------------------+
| archival-state | etag                                 | md5                      | name               | size   | storage-tier | time-created                     | time-modified                    |
+----------------+--------------------------------------+--------------------------+--------------------+--------+--------------+----------------------------------+----------------------------------+
| None           | e0030182-3850-4e52-9ef8-567c794b63b8 | H8scWcchoH1XrSuTgTTehA== | expdp.par          | 193    | Standard     | 2021-02-18T13:09:02.178000+00:00 | 2021-03-05T15:03:21.412000+00:00 |
| None           | 647876cf-dd32-4d07-8a75-6e5fb2b8a0de | Fd3Oqm702wD8TQqt3odybw== | expdp2.par         | 145    | Standard     | 2021-02-18T12:14:47.533000+00:00 | 2021-02-18T12:14:47.620000+00:00 |
+----------------+--------------------------------------+--------------------------+--------------------+--------+--------------+----------------------------------+----------------------------------+

Filtering

The query language JMESPath is supported by the OCI CLI. This allows the filtering of the JSON response to the minimum required set of objects and pieces of information. To provide a filter to an OCI CLI request, add the parameter –query.

A good starting point to get familiar with JMESPath is the tutorials area on its website.

As you can see from the above JSON response, all information is encapsulated in an array with the key data. So every query has to start with this key. The following calls would return all available array elements.

$> oci ... --query "data"
$> oci ... --query "data[?]"

If for example I want the first element only or a range of elements, the position(s) has/have to be provided.

$> oci ... --query "data[0]"
$> oci ... --query "data[0:2]"

Now I want to reduce the returned information to the keys name and size.

$> oci ... --query "data[0].{Name:name,Size:size}"
{
  "Name": "expdp.par",
  "Size": 193
}

$> oci ... --query "data[0].{Size:size,Name:name}" --output table
+-----------+------+
| Name      | Size |
+-----------+------+
| expdp.par | 193  |
+-----------+------+

The column position within the {..} is not honored. Instead, the columns are ordered in alphabetical order. To change the order, add a number to the column names. Be aware that in this case, the column names have to be escaped with \”xxx\”.

$> oci ... --query "data[0].{\"1 Size\":size,\"2 Name\":name}" --output table
+--------+-----------+
| 1 Size | 2 Name    |
+--------+-----------+
| 193    | expdp.par |
+--------+-----------+

Escaping is also required, when the key includes a hyphen, e.g. \”time-created\”.

It is also possible to filter the elements of a JSON array using expressions. For example, get information about a file with the name expdp2.par. As far as I know, wildcard searches are not possible, but most of the use cases can be replaced by using the contains function.

$> oci ... --query "data[?name == 'expdp2.par'].{\"1 Size\":size,\"2 Name\":name}" --output table
+--------+------------+
| 1 Size | 2 Name     |
+--------+------------+
| 145    | expdp2.par |
+--------+------------+

$> oci ... --query "data[?contains(name,'.par')].{\"1 Size\":size,\"2 Name\":name}" --output table
+--------+------------+
| 1 Size | 2 Name     |
+--------+------------+
| 193    | expdp.par  |
| 145    | expdp2.par |
| 169    | expdp3.par |
+--------+------------+

If you have queries which are used frequently, you can define an alias for it in ~/.oci/oci_cli_rc.

$> vi ~/.oci/oci_cli_rc
...
[OCI_CLI_CANNED_QUERIES]
get_expdp_file=data[?name == 'expdp2.par'].{"1 Size":size,"2 Name":name}

Escaping is not required when the oci_cli_rc file is used. The defined alias can then be used for a query.

$> oci ... --query query://get_expdp_file --output table
+--------+------------+
| 1 Size | 2 Name     |
+--------+------------+
| 145    | expdp2.par |
+--------+------------+

Summary

After investigating some time into JMESPath, filtering the JSON response of the OCI CLI is easy and very useful to get rid of all information that is not required. With the help of the table-formatted output, nice reports can be created.

References

Leave a Reply

Your email address will not be published.