TECH

ついに公開されたAPIをGoから利用する(契約情報を取得する)

TECH
中津川 篤司

CloudGarageのインスタンス操作などを自動化できるAPIがついに公開されました。これでインスタンスの立ち上げや停止を自動化できるようになります。

そこで今回はGoを使ってAPI操作を行う方法を解説します。契約情報を取得します。

必要なソフトウェア、ライブラリ

今回必要なソフトウェア、ライブラリは以下の通りです。

  • Go

APIキーを取得する

続いてCloudGarageの管理画面にてAPIキーを取得します。管理画面の右上にあるメニューをクリックして、アカウント情報確認/変更を選択します。

一度パスワードを入力する必要があります。

そして一番下にあるAPI Key管理にてAPI Keyを発行します。私はすでに発行済みなので再発行になっていますが、最初はAPIキーがないはずです。Client ID(クライアントID)とClient Secret(クライアントシークレット)の二つで認証します。重要なキーなので漏洩したりしないよう注意してください。

設定ファイルを読み込む

APIキーを記述したファイル(config.json)を読み込みます。GoではJSONを扱う際に、まずその構造に合わせて構造体を作っておく必要があります。この場合、Config という構造体になります。

type Config struct {
  ClientId     string `json:"client_id"`
  ClientSecret string `json:"client_secret"`
}

そしてファイルを読み込みます。

// APIキーの取得
config, err := loadConfig()
if err != nil {
  log.Fatal(err)
}

// 読み込む関数
func loadConfig() (Config, error) {
  // APIキーの取得
  bytes, err := ioutil.ReadFile("./config.json")
  if err != nil {
    log.Fatal(err)
  }
  var config Config
  err = json.Unmarshal(bytes, &config)
  return config, err
}

トークンを取得する

まずAPIを利用するためのトークンを取得する必要があります。コードは次のようになります。 POST /tokens リクエストして、その結果として得られるJSONの token.id の値がトークンになります。

今回の構造体は以下のようになります。

type Token struct {
  Value TokenValue `json:"token"`
}
type TokenValue struct {
  Id string `json:"id"`
  Expires string `json:"expires"`
  ClientId string `json:"client_id"`
}

そしてトークンを取得するコードです。

// トークンの取得
token, err := getToken(baseUrl, config)

// トークンを取得する関数
func getToken(baseUrl string, config Config) (string, error) {
  url := baseUrl + "/tokens"
  params, err := json.Marshal(config)
  res, err := http.Post(url, "application/json", bytes.NewBuffer(params))
  body, err := ioutil.ReadAll(res.Body)
  var token Token
  if err := json.Unmarshal(body, &token); err != nil {
    log.Fatal(err)
  }
  defer res.Body.Close()
  return token.Value.Id, err
}

CloudGarageのAPIでは {token: { id: ... }} といった具合にレスポンスのJSONがデータモデルのキーでラップされています。そのため Token と TokenValue のように一段階ネストした構造になっています。

契約情報の一覧を取得する

トークンを取得したら、そのトークンを使って契約情報の一覧を取得します。こちらもまず構造体を定義します。

type ContractsJson struct {
  Value []Contract `json:"contracts"`
}
type Contract struct {
  Id int `json:"contract_id"`
  Status string `json:"contract_status"`
  ProductName string `json:"product_name"`
  UsedServerCount int `json:"used_server_count"`
  ContractDateFrom string `json:"contract_date_from"`
  ContractDateTo string `json:"contract_date_to"`
  Price int `json:"price"`
  PriceInit int `json:"price_init"`
  ResourceInfo ResourceInfo `json:"resource_info"`
}

そして契約情報の一覧を取得します。getはこの後の契約情報詳細を取得する際にも使います。GETリクエストを行って、その結果をバイト文字列で返します。

// 契約情報の一覧を取得
contracts, err := getContracts(baseUrl, token)

func getContracts(baseUrl string, token string) ([]Contract, error) {
  url := baseUrl + "/contracts"
  body, err := get(url, token)
  var contractsJson ContractsJson
  if err := json.Unmarshal(body, &contractsJson); err != nil {
    log.Fatal(err)
  }
  return contractsJson.Value, err
}

// GETリクエストを行う処理
func get(url string, token string) ([]byte, error){
  req, _ := http.NewRequest("GET", url, nil)
  req.Header.Set("Content-Type", "application/json")
  req.Header.Set("X-Auth-Token", token)
  client := new(http.Client)
  res, err := client.Do(req)
  body, err := ioutil.ReadAll(res.Body)
  defer res.Body.Close()
  return body, err
}

契約情報詳細を取得する

契約情報IDを取得したら、さらに詳細を取得します。これは GET /contracts/{id} となっています。

構造体としては契約情報自体は変わらないので、そのモデルキーになる構造体だけ定義します。さらにCPUやメモリ、ストレージとしたリソース情報を入れる構造体も定義します。

type ContractJson struct {
  Value Contract `json:"contract"`
}

type ResourceInfo struct {
  CpuMax int `json:"cpu_max"`
  MemoryMax int `json:"memory_max"`
  DiskMax int `json:"disk_max"`
  CpuUsed int `json:"cpu_used"`
  MemoryUsed int `json:"memory_used"`
  DiskUsed int `json:"disk_used"`
}

そして契約情報の詳細を得るためのコードです。

// 契約情報の詳細を取得
contract, err := getContract(baseUrl, token, contracts[0].Id)
log.Println(contract)

func getContract(baseUrl string, token string, id int) (Contract, error){
  url := baseUrl + "/contracts/" + strconv.Itoa(id)
  body, err := get(url, token)
  log.Println(string(body))
  var contractJson ContractJson
  if err := json.Unmarshal(body, &contractJson); err != nil {
    log.Fatal(err)
  }
  return contractJson.Value, err
}

結果として、次のような出力が得られます。

{114581 契約中 C4 1 2018/09/03  2959 0 {2 4 100 1 2 50}}

Goの場合、構造体を作るのが若干の手間かも知れません。しかしCloudGarage APIのようにRESTfulの原則に則っていれば構造体の使い回しも効きます。Goのコードは見やすく書けますのでぜひ使ってみてください。

APIリファレンスはCloudGarage API リファレンスにありますので、ぜひご覧ください。

この記事を書いた人

中津川 篤司

株式会社MOONGIFT 代表取締役。CloudGarage、ニフクラ mobile backend、hifive エバンジェリスト。プログラマ、エンジニアとしていくつかの企業で働き、28歳のときに独立。2004年、まだ情報が少なかったオープンソースソフトの技術ブログ『MOONGIFT』を開設し、毎日情報を発信している。2013年に法人化、ビジネスとエンジニアを結ぶエバンジェリスト業「DevRel」活動をスタートした。 Twitter:@goofmint | GitHub:@goofmint | Facebook: goofmint

この記事のタグ

オススメの記事

ページトップへ