Hello, Gophercloud

Image by aisvri / Unsplash

I’ve been playing around with Gophercloud over the past few days. While it’s nowhere near as complete as openstacksdk (which, coincidentally, recently hit the big 1.0.0 milestone 🎉) or legacy Python-based service clients yet, it is clearly a great tool to have in your arsenal and is the library underlying the Terraform OpenStack Provider, OpenStack platform support in openshift-install, and various OpenStack-specific Kubernetes components, among others.

In the interests of easing ramp-up for anyone else trying to get started with Gophercloud, here’s an simple “hello, world” example - listing servers - using both Gophercloud and openstacksdk.

Gophercloud (Go)

Create a new directory containing a single file, main.go, and add the following to it.

package main

import (
	"fmt"

	"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
	"github.com/gophercloud/utils/openstack/clientconfig"
)

func main() {
	opts := new(clientconfig.ClientOpts)
	// We could configure the cloud manually but we don't. Instead we'll leave it unset causing gophercloud to load the
	// cloud from the 'OS_CLOUD' environment variable. We could also simplify this further and pass 'nil' below instead
	// of generating and passing a 'ClientOpts' object but this shows how you _could_ configure things if you so chose.
	// opts.Cloud = "devstack-admin"

	client, err := clientconfig.NewServiceClient("compute", opts)
	if err != nil {
		fmt.Println(err)
		return
	}

	pager, err := servers.List(client, nil).AllPages()
	if err != nil {
		fmt.Println(err)
		return
	}

	servers, err := servers.ExtractServers(pager)
	if err != nil {
		fmt.Println(err)
		return
	}

	fmt.Println("servers:")
	for i, server := range servers {
		fmt.Printf("  server %d: id=%s\n", i, server.ID)
	}
}

Now generate the go.mod file.

❯ go mod init gophercloud-hello-world
❯ go mod tidy

Finally, you can run the command.

❯ export OS_CLOUD=devstack-admin  # or another entry from your local 'clouds.yaml'
❯ go run .

This should dump something like the following.

servers:
  server 0: id=395b60b4-73be-4ba4-a8a8-fdaa3fce57d5

openstacksdk (Python)

Create a new directory containing a single file, main.py, and add the following to it.

import openstack

def main():
    # We could configure the cloud manually but we don't. Instead we'll leave it unset causing openstacksdk to load the
    # cloud from the 'OS_CLOUD' environment variable.
    # conn = openstack.connect(cloud='devstack-admin')
    conn = openstack.connect()

    servers = conn.compute.servers()

    print('servers:')
    for i, server in enumerate(servers):
        print(f'  server {i}: id={server.id}')

if __name__ == '__main__':
    main()

Now create a virtual environment and install the dependencies.

❯ virtualenv .venv
❯ source .venv/bin/activate
❯ pip install openstacksdk

Finally, you can run the command.

❯ export OS_CLOUD=devstack-admin  # or another entry from your local 'clouds.yaml'
❯ python main.py

This should dump identical output to the Go-based script.

servers:
  server 0: id=395b60b4-73be-4ba4-a8a8-fdaa3fce57d5
comments powered by Disqus