RubyでAPIを叩く(#2 DigitalOcean curl編)


[前回](http://qiita.com/kazuyat/items/2234937591a73a0109a0)は小手調べとしてDigitalOcean公式SDKを使っての操作をしてみました。

最終目的はライブラリなしでAPIリクエストをラップしていくことですが、その前にDigitalOceanのAPIを直接叩く練習をしてみます。

とは言っても、DigitalOceanの[API仕様書](https://developers.digitalocean.com/documentation/v2/)がしっかりしているので、その通りになぞってみるだけになるような気もしますが…。

## 基本的なスタイル

まず、DigitalOceanのDroplet操作用APIエンドポイントは`https://api.digitalocean.com/v2/droplets`です。ここに向けてcurlコマンドでGETなりPOSTなりDELETEなりのHTTPリクエストを打ち込みます。

前回と同様、APIトークンを使いますのでまずは環境変数に入れておきます。

```
TOKEN=(取得したトークン）
```

DigitalOceanの他のリソース、例えばドメインとかも積極的にいじっていくなら、エンドポイントURLも環境変数に入れておいてもいいかもしれません。

```
DROPLET_EP=https://api.digitalocean.com/v2/droplets
```

curlコマンドを使って、Droplet一覧を出力してみます。jqは鉄板ですね！

```
curl -X GET $DROPLET_EP -H "Authorization: Bearer $TOKEN" | jq
{
  "droplets": [],
  "links": {},
  "meta": {
    "total": 0
  }
}
```

…はい、何も出てきません。Dropletを一つも作っていないんで…。

なお、curlのデフォルトがGETメソッドなので、GETのときは-Xオプションはなくてもいいです。

では次にDropletを作ってみます。

## Dropletを作る

POSTメソッドを打ち出す場合、
* `-X POST`を付与する
* Content-Typeとしてapplication/jsonヘッダを付与する
* `-d`オプションにボディ(JSON)をセットする
必要があります。

また、ボディの中身を用意する必要があります。前回と同じ、かつAPIサンプルほぼまんまですが、

```
{
  "name": "testserver",
  "region": "sgp1",
  "size": "512MB",
  "image": "ubuntu-14-04-x64",
  "ipv6": "false"
}
```
とします(例によって不完全です)。

```
curl -X POST $DROPLET_EP -H "Authorization: Bearer $TOKEN" -H pplication/json" -d '{ "name": "testserver", "region": "sgp1", "size": "512mb", "image": "ubuntu-14-04-x64", "ipv6": "false" }'

{"droplet":{"id":26666109,"name":"testserver","memory":512,"vcpus":1,"disk":20,"locked":true,"status":"new","kernel":null,"created_at":"2016-09-23T15:45:48Z","features":["virtio"],"backup_ids":[],"next_backup_window":null,"snapshot_ids":[],"image":{"id":19780649,"name":"14.04.5 x64","distribution":"Ubuntu","slug":"ubuntu-14-04-x64","public":true,"regions":["nyc1","sfo1","nyc2","ams2","sgp1","lon1","nyc3","ams3","fra1","tor1","sfo2","blr1"],"created_at":"2016-09-19T19:22:40Z","min_disk_size":20,"type":"snapshot","size_gigabytes":0.45},"volume_ids":[],"size":{"slug":"512mb","memory":512,"vcpus":1,"disk":20,"transfer":1.0,"price_monthly":5.0,"price_hourly":0.00744,"regions":["ams1","ams2","ams3","blr1","fra1","lon1","nyc1","nyc2","nyc3","sfo1","sfo2","sgp1","tor1"],"available":true},"size_slug":"512mb","networks":{"v4":[],"v6":[]},"region":{"name":"Singapore 1","slug":"sgp1","sizes":["512mb","1gb","2gb"],"features":["private_networking","backups","ipv6","metadata"],"available":true},"tags":[]},"links":{"actions":[{"id":147866852,"rel":"create","href":"https://api.digitalocean.com/v2/actions/147866852"}]}}
```

グワーッと、出ました(jq入れ忘れた…）。最初に打ち出していたDroplet一覧APIをもう一度叩いてみます。

```
{
  "droplets": [
    {
      "id": 26666109,
      "name": "testserver",
      "memory": 512,
      "vcpus": 1,
      "disk": 20,
      "locked": false,
      "status": "active",
      "kernel": null,
      "created_at": "2016-09-23T15:45:48Z",
      "features": [
        "virtio"
      ],
      "backup_ids": [],
      "next_backup_window": null,
      "snapshot_ids": [],
      "image": {
        "id": 19780649,
        "name": "14.04.5 x64",
        "distribution": "Ubuntu",
        "slug": "ubuntu-14-04-x64",
        "public": true,
        "regions": [
          "nyc1",
          "sfo1",
          "nyc2",
          "ams2",
          "sgp1",
          "lon1",
          "nyc3",
          "ams3",
          "fra1",
          "tor1",
          "sfo2",
          "blr1"
        ],
        "created_at": "2016-09-19T19:22:40Z",
        "min_disk_size": 20,
        "type": "snapshot",
        "size_gigabytes": 0.45
      },
      "volume_ids": [],
      "size": {
        "slug": "512mb",
        "memory": 512,
        "vcpus": 1,
        "disk": 20,
        "transfer": 1,
        "price_monthly": 5,
        "price_hourly": 0.00744,
        "regions": [
          "ams1",
          "ams2",
          "ams3",
          "blr1",
          "fra1",
          "lon1",
          "nyc1",
          "nyc2",
          "nyc3",
          "sfo1",
          "sfo2",
          "sgp1",
          "tor1"
        ],
        "available": true
      },
      "size_slug": "512mb",
      "networks": {
        "v4": [
          {
            "ip_address": "(グローバルIP)",
            "netmask": "255.255.192.0",
            "gateway": "128.199.192.1",
            "type": "public"
          }
        ],
        "v6": []
      },
      "region": {
        "name": "Singapore 1",
        "slug": "sgp1",
        "sizes": [
          "512mb",
          "1gb",
          "2gb"
        ],
        "features": [
          "private_networking",
          "backups",
          "ipv6",
          "metadata"
        ],
        "available": true
      },
      "tags": []
    }
  ],
  "links": {},
  "meta": {
    "total": 1
  }
}
```
今度は出てきました(jqも入れた！)。縦に長いですが、jqの整形で読みやすいです。DigitalOceanのGUIからも作成できていることが確認できました。

## curlで消してみる

せっかくDropletを作りましたが、今度は消してみます。
前回SDKでやったときと同様、IDさえ分かれば消すことは可能です。作成したDropletは、URIとして以下のように表現されます。

`https://api.digitalocean.com/v2/droplets/(ID)`

このURLをエンドポイントにして、DELETEメソッドを投げてあげます。

先程確認したとおり、このDropletのIDは「26666109」ですので、curlのイメージは

```
curl -X DELETE https://api.digitalocean.com/v2/droplets/26666109 -H "Authorization: Bearer $TOKEN"
```
となります。

RESTの原則？に比較的忠実なAPIは、例えばDELETEメソッドで打てばあまりごちゃごちゃと応答を返さず、静かに200応答だけ返してきます。逆に全部GETとかPOSTだけでやらせるようなAPIは、応答がうるさい？気がします…。

再度GUIやDroplet確認APIを叩いても、もうDropletはいなくなっています。

## 今回Ruby関係なかったですが

直接APIを叩くとき、何が固定で何が可変(すなわち管理対象)なのかを学ぶことができました。次回からRubyを使ってこれらのAPIを叩いてみたいと思います。