gophercloudでConoHa APIに接続する

この記事はConoHa Advent Calendar20日目です。

[ワンボタンでキミのConoHaにGentooが！](https://qiita.com/nothink/items/be2794b9cb741f39e177) (前) < | > (次)[スタートアップスクリプトでこのはちゃんにしゃべってもらいたかった](https://qiita.com/ezaki/items/9eaaf283f1944539d5d8)

----------

こんにちは、[ひろのぶ](https://twitter.com/hironobu_s/)です。メリークリスマス🎄🎄🎄

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">そしてConoHa Advent Calendarの20日目がまだ！！！！ぜひ「ここは私が！」という方がいればぜひ😭😭<a href="https://t.co/uAtNZKfCtT">https://t.co/uAtNZKfCtT</a></p>&mdash; 美雲このは🎄12/12 CD発売！ (@MikumoConoHa) <a href="https://twitter.com/MikumoConoHa/status/945097558925361153?ref_src=twsrc%5Etfw">2017年12月25日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


というわけで代打エントリーです。大分前に作った[novassh](https://github.com/hironobu-s/novassh)というツールをもとに、GoからConoHa APIを叩く話(導入編)をゆるく書いてみたいと思います。

## gophercloud

APIを叩くのにGoの標準パッケージである[net/http(https://golang.org/pkg/net/http/)を使っても良いのですが、OpenStack API(ConoHa API)は複数回のリクエストを行うことが多いので、SDKを使った方が簡単に実装できます。

[gophercloud](https://github.com/rackspace/gophercloud)は[Rackspace社](https://www.rackspace.com/)が開発しているGo言語のOpenStack SDKです。RackspaceのクラウドはOpenStackをベースにしていて、このライブラリは自社クラウド向けのSDKという位置づけのようです。ただ一般的なOpenStack基盤でも利用できるようネームスペースが分かれていて、OpenStackをベースにしているConoHaでも使うことができます。

> ちなみに、Rackspaceは大分前にパブリッククラウドを止めてマネージドクラウドのみになったので、現在はお手軽に試すことはできなくなってしまいました。


## 使い方

> [ConoHa APIのリファレンス](https://conoha.jp/docs/)も併せてご覧ください

ConoHa APIを使う順番として、まずIdentity APIで認証を行い、その後各サービスのAPI(ComputeやBlockStorageやNetworkなど)を呼ぶことになります。

gophercloudはこのあたりを抽象化してくれるので非常に簡単です。

```go
package main

import (
    "github.com/rackspace/gophercloud"
    "github.com/rackspace/gophercloud/openstack"
)

func main() {
    // APIの認証情報を設定する
    opts := gophercloud.AuthOptions{
        IdentityEndpoint: "https://identity.tyo1.conoha.io/v2.0",
        Username:         "gncu********",
        TenantName:       "gnct********",
        Password:         "************",
    }

    // AuthenticatedClient() は内部で認証を行い、
    // 各サービス(Compute, Network, Storageなど)の
    // 接続に使われるクライアントを返します。
    client, err := openstack.AuthenticatedClient(opts)
    if err != nil {
        panic(err)
    }

    // このclientは内部に token を保持しています。
    println(client.TokenID)
}
```

例としてCompute APIを呼んでみます。サーバー一覧を表示するサンプルは以下のようになります。

```go
    // 今回は例としてCompute APIを使います。
    // gophercloudでは各サービスへのAPIアクセスをProvider構造体に抽象化されていて、
    // openstackパッケージにあるNewComputeV2()を呼ぶと、
    // Compute APIへアクセスする情報がセットされたクライアントが返ってきます。
    eo := gophercloud.EndpointOpts{
        Type:   "compute",
        Region: "tyo1",
    }
    compute, err := openstack.NewComputeV2(client, eo)
    if err != nil {
        panic(err)
    }

    // Compute APIの各機能は
    // github.com/rackspace/gophercloud/openstack/compute/v2/servers
    // パッケージにあります。
    // 各機能を実行するにはクライアント(compute)を渡す必要があります。
    listOpts := servers.ListOpts{}
    pager := servers.List(compute, listOpts)
    pager.EachPage(func(page pagination.Page) (bool, error) {
        serverList, err := servers.ExtractServers(page)
        if err != nil {
            return false, err
        }
        for _, server := range serverList {
            fmt.Printf("%v\n", server)
        }
        return true, nil
    })
```

もう一つの例としてVPSを作成してみましょう。servers.CreateOpts構造体にパラメータを埋めてCreate()を叩くだけでとても簡単です。

```go
    // VPSを作成するような複雑なリクエストもとても簡単です。
    // ただ、gophercloudはConoHa独自のパラメータに対応していません。
    // たとえば管理者パスワードを設定する"adminPass"や、
    // SSHの公開鍵を指定する"key_name"などです。
    //
    // これらを指定する場合はuser_dataを使うことになります。
    // https://www.conoha.jp/guide/startupscript.php
    copts := servers.CreateOpts{
        Name:      "gophercloud-test",
        ImageRef:  "b9e54c41-cda9-4d84-8248-808bfaf6c793",
        FlavorRef: "7eea7469-0d85-4f82-8050-6ae742394681",
        SecurityGroups: []string{
            "default",
            "gncs-ipv4-all",
            "gncs-ipv6-all",
        },
        Metadata: map[string]string{
            "instance_name_tag": "gophercloud-test",
        },
    }
    r := servers.Create(compute, copts)
    if r.Err != nil {
        panic(r.Err)
    }
```

上記のスクリプトは抜粋で、全文は[Gist](https://gist.github.com/hironobu-s/09be8f7e7422f5a477182a871ae8d6ca)にあります。

また、私が作った[conoha-net](https://github.com/hironobu-s/conoha-net/)では、同じ要領でNetwork APIを実行しているので、こちらもご参考までに

[https://github.com/hironobu-s/conoha-net/blob/master/conoha/network.go](https://github.com/hironobu-s/conoha-net/blob/master/conoha/network.go)

gophercloudを使うと、ConoHa APIを使った開発がとても簡単になると思います。

## ちょっとnovasshの話

novasshは**IPアドレスの代わりにインスタンス名でVPSにSSHできる**ツールで、ConoHaで使うとなかなか便利です。コントロールパネルからIPアドレスをコピペする必要がなくなります。またシリアルコンソール接続もできるので、SSHが落ちた場合でもVPSに接続できます。

良かったら下記の記事もご覧ください。

[OpenStackインスタンスに簡単にSSHできるツールnovasshを作った](https://qiita.com/hironobu_s/items/ca4b7f8817c395ed0478)

[github.com/hironobu-s/novassh](https://github.com/hironobu-s/novassh)


## おわりに

Gopherくんかわいいよね！ [ʕ◔ϖ◔ʔ](https://blog.golang.org/gopher)