gscloud – The Official CLI Client for gridscale

Date: 19.10.2020

gridscale gs cloud CLI Clienttl;dr – gscloud is a helpful tool for managing servers and other resources directly from the command line.

Introduction

Who doesn’t appreciate a well thought-out user interface that helps us to quickly grasp what is possible and guide us smoothly through complex tasks? The gridscale panel is one such interface that helps us learn the ropes and enables complex tasks to be carried out swiftly without much learning upfront. My colleagues work hard at making it even better every day.

However, when confronted with tasks on a scale even slightly larger than usual many of us prefer to return to the command line. Imagine turning off thirty servers at once. Not much fun if you need to click repeatedly, right? Apart from the usual dullness that comes with repetition we often like to automate tasks that need to be carried out often or are prone to manual error. We usually start writing scripts in our favourite scripting language. For many of us, this is the shell.

For this reason, we have begun working on a new tool we’ve named gscloud. While it is far from being finished, we have made so much progress that we want to tell you about it.

gscloud makes use of the gridscale API and offers you access to all1 your objects and resources directly from the command line. It is written in Go and it works on macOS, Windows, and Linux. I heard that someone has already made a package for the FreeBSD ports tree.

Installation

Right now, the preferred way to install gscloud is to grab the latest official release from [GitHub]. It is just one binary. Download the zip archive for your platform (available for Windows, Linux, and macOS, among others) and unzip it in your PATH.

$ gscloud version
Version:        v0.4.0
Git commit:     e89fd0c5e909ef69136b18652127a4fafd44e787

 

If this works, you are ready to start.

General Usage

This demo uses gscloud on Linux but it’ll be very much the same for macOS and Windows.
Type:

$ gscloud help

 

gscloud lets you manage objects on gridscale.io via command line. It provides
a Docker-CLI comparable command line that allows you to create, manipulate, and
remove objects on gridscale.io.

Usage:
  gscloud [command]

Available Commands:
  completion  Generate shell completion scripts
  help        Help about any command
  kubernetes  Operate managed Kubernetes clusters
  make-config Create a new configuration file
  manpage     Create man-pages for gscloud
  network     Operations on networks
  server      Operations on servers
  ssh-key     Operations on SSH keys
  storage     Operations on storages
  template    Operations on templates
  version     Print the version

Flags:
      --account string   Specify the account used (default "default")
      --config string    Specify a configuration file (default "~/.config/gscloud/config.yaml")
  -h, --help             Print usage
  -j, --json             Print JSON to stdout instead of a table
      --noheading        Do not print column headings
  -q, --quiet            Print only IDs of objects

Use "gscloud [command] --help" for more information about a command.

 

This shows you all available commands. Let start with creating a config file.

$ gscloud make-config
Written: ~/.config/gscloud/config.yaml

$ cat ~/.config/gscloud/config.yaml
accounts:
- name: default
  userId: ""
  token: ""
  url: https://api.gridscale.io

 

Let’s hop over to the panel and copy our user ID and create an API token to fill in here. After that, we can just use that token to interact with all objects within the corresponding project2. You can specify multiple accounts in the config file. Use the name in the config to identify the project the token belongs to.

Let’s say we have two separate projects, `dm` and `dm-staging`, which might look like this:

$ cat ~/.config/gscloud/config.yaml
accounts:
- name: dm
  userId: 3737b9ab-65ff-4d1e-af5e-d08d683bd1fa
  token: ec83ea6e8ce4739d62421fc062acf9e90777608a938eae34203aa52d9ddc72b7
  url: https://api.gridscale.io

- name: dm-staging
  userId: 3737b9ab-65ff-4d1e-af5e-d08d683bd1fa
  token: fc5a2557e3009d48ed7a031b1dee4630a0e1d84d19b646de712a1dbc71fc6045
  url: https://api.gridscale.io

$ gscloud --account=dm server ls
ID                                    NAME  CORE  MEM  CHANGETIME                 POWER
1c8e481e-b930-4fca-9c30-77b5a6da6412  dm-1  1     2    2020-09-06T20:44:26+02:00  on
4698ae6e-96ad-4214-8fc0-7407d7e8b3f8  dm-2  4     8    2020-09-06T20:44:24+02:00  on
d0d8a330-2a3c-4b65-b159-c9915e00fced  dm-3  4     8    2020-09-06T20:45:21+02:00  off

$ gscloud --account=dm-staging server ls
ID  NAME  CORE  MEM  CHANGETIME  POWER

 

With `gscloud server ls` we list all server objects. Clearly we have a bunch of servers in `dm` but so far nothing in `dm-staging`. But before we start creating some, let’s quickly note the way commands are given. Most commands take the following form:

$ gscloud server ls
$ gscloud server rm 
$ gscloud server create --name whatever

 

Note how commands are `gscloud `. Equipped with this little mnemonic, remembering the different commands should be easy enough.

Creating and Deleting Objects

Removing a server is simple. Just give it the ID.

$ gscloud --account=dm server ls
ID                                    NAME  CORE  MEM  CHANGETIME                 POWER
4698ae6e-96ad-4214-8fc0-7407d7e8b3f8  dm-2  4     8    2020-09-06T20:44:24+02:00  on
d0d8a330-2a3c-4b65-b159-c9915e00fced  dm-3  4     8    2020-09-06T20:45:21+02:00  off
1c8e481e-b930-4fca-9c30-77b5a6da6412  dm-1  1     2    2020-09-06T20:44:26+02:00  on

 

Let’s go:

gridscale/gscloud $ gscloud --account=dm server rm d0d8a330-2a3c-4b65-b159-c9915e00fced

 

Let’s check:

gridscale/gscloud $ gscloud --account=dm server ls
ID                                    NAME  CORE  MEM  CHANGETIME                 POWER
4698ae6e-96ad-4214-8fc0-7407d7e8b3f8  dm-2  4     8    2020-09-06T20:44:24+02:00  on
1c8e481e-b930-4fca-9c30-77b5a6da6412  dm-1  1     2    2020-09-06T20:44:26+02:00  on

 

Et voilà. Gone.

There is also a `–quiet` flag that suppresses everything and just gives you object IDs.

$ gscloud --account=dm server ls --quiet
4698ae6e-96ad-4214-8fc0-7407d7e8b3f8
1c8e481e-b930-4fca-9c30-77b5a6da6412

 

You can use this to quickly turn off a bunch of servers off in a loop, e.g.:

$ gscloud server ls --quiet | while read s; do
 ./gscloud server off --force $s
done

 

You can, of course, delete them along with their storages this way, too. But let’s create a new server. (Much more constructive.)

$ gscloud server --account=dm create \
  --cores 1 \
  --mem 1 \
  --name test-1 \
  --with-template "CentOS 8 (x86_64)" \
  --storage-size 15 \
  --hostname test-1 \
  --password secret123
Server created: 9f1376ad-c721-4eb0-8734-791af4a66102
Storage created: 4038e0ba-73c5-4a2e-b2a1-16c3a6433984

 

Note that this will create a storage with the server object. You can also create a storage first and attach it to a new server object. By now, `dm` should look like this:

$ gscloud --account=dm server ls
ID                                    NAME    CORE  MEM  CHANGETIME                 POWER
1c8e481e-b930-4fca-9c30-77b5a6da6412  dm-1    1     2    2020-09-06T20:44:26+02:00  on
9f1376ad-c721-4eb0-8734-791af4a66102  test-1  1     1    2020-09-09T17:45:10+02:00  off

 

Doing More With JSON

With a Unix command line and the usual table-oriented output gscloud gives you on stdout, you should be able to quickly hack up a few simple lines with `sed(1)`, `awk(1)`, `grep(1)` and friends. You probably use them already to extract the data you want and feed it into something else.

Another alternative I want to show you is to use gscloud with the `–json` flag and combine it with `jq(1)`. jq is a command-line JSON processor3. But let’s try it out. Let’s type:

$ gscloud --account=dm server ls --json | jq

 

With the changes we made to the `dm` project above we should now see something like this:

json
[
  {
    "server": {
      "object_uuid": "1c8e481e-b930-4fca-9c30-77b5a6da6412",
      "name": "dm-1",
      "memory": 2,
      "cores": 1,
      "hardware_profile": "q35",
      "status": "active",
      "location_uuid": "8328a5bc-e66e-4edc-8aae-2e2bf07fdb28",
      "power": true,
      "current_price": 2.03693,
      "availability_zone": "",
      "auto_recovery": true,
      "legacy": false,
      "console_token": "13f53ff5a05b85df722ac6bc60a94d620554f876cd91acfb7c048eda2fd55839bf5752cd67d263ca8e3215d630863af2",
      "usage_in_minutes_memory": 8314,
      "usage_in_minutes_cores": 4157,
      "labels": [],
      "relations": {
        "isoimages": [],
        "networks": [],
        "public_ips": [],
        "storages": [
          {
            "object_uuid": "d55d4e80-ba89-4c6c-be70-8c68fb979516",
            "object_name": "dm-1",
            "capacity": 10,
            "storage_type": "storage",
            "target": 0,
            "lun": 0,
            "controller": 0,
            "create_time": "2020-09-06T18:42:02Z",
            "bootdevice": true,
            "bus": 0,
            "last_used_template": "8d1bb5dc-7c37-4c90-8529-d2aaac75d812",
            "license_product_no": 0,
            "server_uuid": ""
          }
        ]
      },
      "create_time": "2020-09-06T18:42:02Z",
      "change_time": "2020-09-06T18:44:26Z"
    }
  },
  {
    "server": {
      "object_uuid": "9f1376ad-c721-4eb0-8734-791af4a66102",
      "name": "test-1",
      "memory": 1,
      "cores": 1,
      "hardware_profile": "default",
      "status": "active",
      "location_uuid": "8328a5bc-e66e-4edc-8aae-2e2bf07fdb28",
      "power": false,
      "current_price": 0,
      "availability_zone": "",
      "auto_recovery": true,
      "legacy": false,
      "console_token": "0bd94037291bde961dbee58c15ff7b4df4b9bd0759435cb7955db1f0e335d15ec6fbfdd6813ae52d5f0fa9406c767c23",
      "usage_in_minutes_memory": 0,
      "usage_in_minutes_cores": 0,
      "labels": [],
      "relations": {
        "isoimages": [],
        "networks": [],
        "public_ips": [],
        "storages": [
          {
            "object_uuid": "4038e0ba-73c5-4a2e-b2a1-16c3a6433984",
            "object_name": "test-1",
            "capacity": 15,
            "storage_type": "storage",
            "target": 0,
            "lun": 0,
            "controller": 0,
            "create_time": "2020-09-09T15:45:28Z",
            "bootdevice": true,
            "bus": 0,
            "last_used_template": "8d1bb5dc-7c37-4c90-8529-d2aaac75d812",
            "license_product_no": 0,
            "server_uuid": ""
          }
        ]
      },
      "create_time": "2020-09-09T15:45:10Z",
      "change_time": "2020-09-09T15:45:10Z"
    }
  }
]

 

This not only gives us nice syntax highlighting but also much more information by default. Also note that the information is more structured. With jq you can go totally nuts and create some powerful expressions.

$ gscloud --account=dm server ls --json \
    | jq -c '.[] | .server | select( .memory > 1 ) | { id: .object_uuid, name: .name, on: .power }'
{"id":"1c8e481e-b930-4fca-9c30-77b5a6da6412","name":"dm-1","on":true}

 

What does this do? It selects all servers in `dm` that currently have more than one gig of memory and constructs a new JSON object for each of them with the server’s ID, name, and power status, printing it to stdout. Anyway, you get the idea. Totally nuts but incredibly useful. (Imagine sorting resources by `”current_price”` to determine what produces most costs.)

What to Expect in Future

We’ll continue adding to gscloud. The goal is to allow you to do everything you can do from within the panel right from your command line, be it Windows’ cmd.exe or PowerShell, be it on Linux, on one of the BSDs, or on macOS.

With this we hope to add a valuable new way for you to interact with your resources at gridscale while at the same time complementing our panel, Terraform provider, and our client libraries to help you interact with the gridscale API from your programs.

Have fun!

Footnotes

1 Well, not quite yet but soon.

2 Remember, API tokens are bound to projects. So when using a token we cannot remove or alter objects in other projects.

3 jq is available here. If you don’t have it installed already, chances are high that a `brew install jq` or `sudo dnf install jq` is all you need to do.

Back to overview