X
  • September 4, 2018

Your Cloud Estate in the Shell

Jesse Butler
Cloud Native Developer Advocate

 

Oracle Cloud has a fully-featured web console that makes managing cloud accounts straightforward and simple. But what if, like me, you are more at home in a shell?  There's a CLI for that.

The aptly-named oci utility is a CLI which offers much of the same functionality as the web console in a nice, compact command line package for Windows, MacOS and Linux.  With it, users can create, destroy, modify and monitor aspects of their OCI estate.

The CLI is organized the same way as the web console, logically following the API. This means that if you're familiar with the console, it'll be pretty easy to poke around and find what you're looking for. For example, images can be found in the console on the side bar under Compute->Images. To list images with the CLI, we invoke:

# oci compute image list

 

Getting Started

To use the CLI, you'll need an OCI account, a user configured in that account along with a policy that allows that user to do useful administrative things, an API keypair and a system with Python installed. Check out the Getting Started section of the OCI documentation, as well sections on Adding Users and Security Credentials.

For configuration, the CLI uses a config file (e.g. ~/.oci/config). This file contains some required OCI-related data, such as user credentials and tenancy info. Some optional data can be laid in there too for ease of use.

Configuration elements are referred to by their OCID, or their Oracle Cloud Identifier. Every Oracle Cloud Infrastructure resource has a unique OCID attached to it. You can collect these from the web console as needed, and we can get things rolling.

For super-quick startup, pop open a shell and say:

# bash -c "$(curl -L https://raw.githubusercontent.com/oracle/oci-cli/master/scripts/install/install.sh)
# oci setup config

This will install the CLI and then drive through creation of a basic configuration. For more detailed installation and configuration instructions, check out the Installing the CLI and Configuring the CLI sections of the CLI documentation.

 

Using the CLI

We can create, destroy and otherwise observe most of the objects within our OCI estate with the CLI. This is really great if your typical workflows are CLI-based, and is also great for scripting various tasks.

As an example to get started, let's create a new bucket in our object store and put a few files in it. Note we need to identify the compartment to create the bucket in. For simplicity's sake we can set an environment variable in our shell to make that easy. We'll discuss an even better way to configure that later on.

# cid=ocid1.compartment.oc1..aaaaaaaa...
# oci os bucket create --compartment-id $cid --name jb2
{
  "data":
    "compartment-id": "ocid1.compartment.oc1..aaaaaaaau7ewrssyclcr4oeoce23dwkziadqtkvaka4s4rjd352367ntbkga",
    "created-by": "ocid1.user.oc1..aaaaaaaaoob2jbqhzmdnzegaej4hkgr22byvg5mnvfnwswlaeorzgwi56ewa",
    "defined-tags": {},
    "etag": "9b66f44e-0bef-42c9-b7e0-bead354bce47",
    "freeform-tags": {},
    "metadata": {},
    "name": "jb2",
    "namespace": "cloudnative-devrel",
    "public-access-type": "NoPublicAccess",
    "storage-tier": "Standard",
    "time-created": "2018-08-30T20:45:32.642000+00:00"
  },
  "etag": "9b66f44e-0bef-42c9-b7e0-bead354bce47"
}

Let's add a couple of files to our object store bucket and list them out.

# for i in 1 2 ; do
mkfile 128k file${i}
oci os object put --compartment-id $cid --bucket-name jb2 --name file${i} --file file${i}
done
Uploading object  [####################################]  100%
{
  "etag": "74AD8A3C39D315A8E053424BC10AF4B4",
  "last-modified": "Thu, 30 Aug 2018 20:47:19 GMT",
  "opc-content-md5": "DfvoqkwgtS4bi/PLbL3xkw=="
}
Uploading object  [####################################]  100%
{
  "etag": "74ADE678D52C7707E053424BC10A8352",
  "last-modified": "Thu, 30 Aug 2018 20:47:50 GMT",
  "opc-content-md5": "DfvoqkwgtS4bi/PLbL3xkw=="
}

# oci os object list --compartment-id $cid --bucket-name jb2
{
  "data": 
    {
      "md5": "DfvoqkwgtS4bi/PLbL3xkw==",
      "name": "file1",
      "size": 131072,
      "time-created": "2018-08-30T20:47:17.286000+00:00"
    },
    {
      "md5": "DfvoqkwgtS4bi/PLbL3xkw==",
      "name": "file2",
      "size": 131072,
      "time-created": "2018-08-30T20:47:48.071000+00:00"
    },
  ],
  "prefixes": []
}

When listing things out, there are a few nice features to help organize and present data in a meaningful way.

Queries

Often the output of a given list command is very noisy when you may only be interested in a couple of key pieces of data. The --query option allows for filtering of the output presented per object.

This option uses the JMESPath query language for JSON. Check out its documentation and dig into sorting out cool, complex queries. Share them with friends and neighbors!

Table Output

JSON is the default output format. For any output list, you can optionally provide the --output table option and argument and get nice table-formatted output.

As an example of putting these two together, we'll list out all of the OCIDs for the CentOS images available to our tenant.

# oci compute image list --compartment-id $cid --operating-system "CentOS" --query 'data[*].{"id":"id","display-name":"display-name"}' --output table

+--------------------------+----------------------------+
| display-name             | id                         |
+--------------------------+----------------------------+
| CentOS-7-2018.08.15-0    | ocid1.image.oc1.iad.aaaaaaaah6ui3hcaq7d43esyrfmyqb3mwuzn4uoxjlbbdwoiicdmntlvwpda |
| CentOS-7-2018.06.22-0    | ocid1.image.oc1.iad.aaaaaaaa5o7kjzy7gqtmu5pxuhnh6yoi3kmzazlk65trhpjx5xg3hfbuqvgq |
ocid| CentOS-7-2018.05.11-0    | ocid1.image.oc1.iad.aaaaaaaal46dansrxksqwbnyburbm6kvqp7zsptjvzxfys7vtydkuo6yezia |
| CentOS-6.9-2018.06.22-0  | ocid1.image.oc1.iad.aaaaaaaanmzl3piptv7um5ewh2ctxjlgtk6fszedwrq2t7f2bruc3swy65aa |
| CentOS-6.9-2018.05.11-0  | ocid1.image.oc1.iad.aaaaaaaa6e4br344oatmwuhhbiopsrk7gtcunksr3p34eokejkp5grbsjwdq |
| CentOS-6.10-2018.08.15-0 | ocid1.image.oc1.iad.aaaaaaaafjth3ljlnwsw2elccwu5igjer64bs3wkly2trqblbkv4ryen6qxq |
+--------------------------+----------------------------+

Note we used the --operating-system option to the oci compute image list command. The list commands have options for filtering the output based upon useful criteria. Another useful example is the --lifecycle-state option on the oci compute instance list command. These are all documented, keep them in mind as you start to work more with the CLI.

 

Customizing the CLI

Working with the oci utility, you'll find yourself typing long-ish strings often. Also, you end up spelling out the same queries repeatedly. Happily both of these sorts of things can be configured.

Like many CLI utilities, oci makes use of an optional run commands shell file (e.g. ~/.oci/oci_cli_rc) to allow for customization. With the rc file, users can define aliases for both commands and options, and also set up more advanced features like formats and canned queries.

To get a stock rc file, you can use

# oci setup oci-cli-rc --file ~/.oci/oci_cli_rc

That will create a basic rc file with some nice queries and aliases to get started with.

A nice feature of this rc file is that you can configure default option arguments for the CLI. For example, if you typically work in a specific compartment, you can set up the compartment-id option as a default option for all commands so you don't need to continually specify it as we've done above.

To set up default options, add a DEFAULT section to your rc file. As an example, I'll add in my compartment-id and bucket-name from the above object store example.

# head -5 .oci/oci_cli_rc
[DEFAULT]
compartment-id = ocid1.compartment.oc1..aaaaaaaa...
bucket-name = jb2

# oci os object list
{
  "data": [
    {
      "md5": "DfvoqkwgtS4bi/PLbL3xkw==",
      "name": "file1",
      "size": 131072,
      "time-created": "2018-08-30T20:47:17.286000+00:00"
    },
    {
      "md5": "DfvoqkwgtS4bi/PLbL3xkw==",
      "name": "file2",
      "size": 131072,
      "time-created": "2018-08-30T20:47:48.071000+00:00"
    },
  ],
  "prefixes": []
}

One more thing to point out is that you can set up pre-canned query formats in your rc file. This is super handy for ones that you use a lot. To get you started, the stock file has a handful of very useful ones. For example, we can use the query string above like so:

# oci compute instance list --operating-system "CentOS" --output table --query query://get_id_and_display_name_from_list

+--------------------------+----------------------------+
| display-name             | id                         |
+--------------------------+----------------------------+
| CentOS-7-2018.08.15-0    | ocid1.image.oc1.iad.aaaaaaaah6ui3hcaq7d43esyrfmyqb3mwuzn4uoxjlbbdwoiicdmntlvwpda |
| CentOS-7-2018.06.22-0    | ocid1.image.oc1.iad.aaaaaaaa5o7kjzy7gqtmu5pxuhnh6yoi3kmzazlk65trhpjx5xg3hfbuqvgq |
| CentOS-7-2018.05.11-0    | ocid1.image.oc1.iad.aaaaaaaal46dansrxksqwbnyburbm6kvqp7zsptjvzxfys7vtydkuo6yezia |
| CentOS-6.9-2018.06.22-0  | ocid1.image.oc1.iad.aaaaaaaanmzl3piptv7um5ewh2ctxjlgtk6fszedwrq2t7f2bruc3swy65aa |
| CentOS-6.9-2018.05.11-0  | ocid1.image.oc1.iad.aaaaaaaa6e4br344oatmwuhhbiopsrk7gtcunksr3p34eokejkp5grbsjwdq |
| CentOS-6.10-2018.08.15-0 | ocid1.image.oc1.iad.aaaaaaaafjth3ljlnwsw2elccwu5igjer64bs3wkly2trqblbkv4ryen6qxq |
+--------------------------+----------------------------+

Nice.

 

Further Reading

We've just gotten started working with oci and can already see how great it is for shell-based workflows. If you find it as handy as I do, I suggest taking a look at the documentation, which is well written and well organized.

Feel free to share any tips and tricks you've picked up along the way here in the comments, and ping me anytime on Twitter @jlb13.

Be the first to comment

Comments ( 0 )
Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.Captcha