さくらのクラウドにTerraformでISUCON12予選の環境を作る

朝起きたらこちらのツイートが流れてきました。

cloud-initで一発で環境構築できるすごいやつですね。ありがとうございます!!

そして

さくらのクラウドにも適用できるはず

とのことなので試しがてらTerraformで一発構築できるようにしてみました。

さくらのクラウドにTerraformでISUCON12環境を作る

こちらにコード類一式を置いておきました。

github.com

手順としてはこんな感じです。

詳しくはREADME.mdを参照してください。

私も環境を作ったばかりでまだ動作確認中なのでおかしいところがあったらご指摘いただけると嬉しいです。

502エラーが出たら

UPDATED: 2022-07-30: この問題は修正されていました
cosmetic by matsuu · Pull Request #10 · matsuu/cloud-init-isucon · GitHub

私の手元では管理画面にログインしようとするとFailed to Login: AxiosError: Request failed with status code 502というエラーが出ていました。 調べたところ認証サービスblackauthが起動していないようでしたので手動で起動しました。

sudo -i -u isucon
sudo systemctl start blackauth

後でこの辺の原因をもうちょい調べてみます。


ということで取り急ぎ公開してみました。 私もこれからじっくり触ってみます。

以上です。

さくらインターネット株式会社に入社しSRE室で働き始めました

本日2022/7/1よりさくらインターネット株式会社に入社いたしました。

これまで主にさくらのクラウド関連OSSの開発という形で関わってまいりましたが、
これからは中の人として色々と活動していくことになりました。

みなさまどうぞよろしくお願いいたします。

どんなお仕事をするの?

所属は本日(7/1)始動のクラウド事業本部 SRE室です。

素敵な仲間と共に、お客様によりよいサービスを提供し、お客様がやりたいことを実現できるように幅広く色々やっていきます。

これまでのOSSのツール類はどうなるの?

引き続き開発/メンテナンスを行います。 従来よりさくらのクラウドCLIであるUsacloudやTerraform/PackerプラグインといったツールをOSSで提供していましたが、より安心/安定して使えるように引き続き取り組みます。

直近だとsacloud/autoscalerを用いたオートスケール機能がベータ版として提供開始されましたので正式リリース目指して頑張ります。

フリーランスとして受けてたお仕事はどうするの?

フリーランスとしてのお仕事は減らしましたが、継続中の案件についてはもちろん対応していきます。
当面は新規でのお仕事を受ける余裕はないと思いますが、そのうち落ち着いたら副業という形で再開するつもりです。

ということで

まずは試用期間を無事に乗り切れるように頑張ります。 今後ともよろしくお願いいたします。

さくらのクラウド: シンプル監視のWebhookでIFTTTと連携してみる

シンプル監視のアラート通知先にIFTTTとZapierが追加されました。

cloud-news.sakura.ad.jp

昨年末にZapierからさくらのクラウドAPIをポーリングする方法について記事を書きましたが、Webhookが使えるようになると出来ることの幅が広がりますね!

febc-yamamoto.hatenablog.jp

ということで連携を試してみました。

IFTTTと連携してみる

今回はシンプル監視からのWebhookを受けたら何かしてみます。

IFTTT側でアプレットを作成

まず新しくアプレットを作成します。If Thisの方をWebhookにします。

Webhookには2つのトリガーが用意されています。 送られてくるJSONはSlackのIncoming webhookに準拠したフォーマットとなっているので左の方を選びます。

なおシンプル監視から送られてくるJSONの例は以下のようなものでした。 参考: さくらのクラウド マニュアル: Zapier、IFTTTのWebhook URLに送信されるJSONの例

{
  "icon_url": "https://secure.sakura.ad.jp/cloud/iaas/sacloud/img/logo/cloud_logo_slack.png",
  "attachments": [
    {
      "color": "danger",
      "fields": [
        {
          "short": "false",
          "value": "113100******",
          "title": "リソースID"
        },
        {
          "short": "false",
          "value": "203.0.113.5",
          "title": "監視対象"
        },
        {
          "short": "false",
          "value": "(監視対象の説明)",
          "title": "説明"
        },
        {
          "short": "true",
          "value": "ping",
          "title": "プロトコル"
        },
        {
          "short": "false",
          "value": "CRITICAL - 203.0.113.5: rta nan, lost 100%",
          "title": "ログ"
        }
      ],
      "text": "2022-03-18 11:35:13 にアラートを検知しました。",
      "title": "ダウン検知 203.0.113.5",
      "fallback": "ダウン検知 203.0.113.5"
    }
  ],
  "username": "sacloud-simplemonitor"
}

次にこのWebhookに名前(Event Name)を付ける必要があります。 ここで入力した値は後ほどシンプル監視を設定する時にWebhookのURLの一部となります。

後のThen Thatの部分はお好みで設定してください。

IFTTT側のWebhookのURLを確認する

アプレットを作成したらWebhookの送信先となるURLを確認します。 以下のページの「Documentation」ボタンから確認ページにいけます。

ifttt.com

この記事の執筆時点ではURLは以下のような形式になっています。

https://maker.ifttt.com/trigger/{イベント名}/json/with/key/{アカウントごとのキー}

カッコ内は適切に置き換えます。

  • {イベント名}: アプレット作成時に指定した名前
  • {アカウントごとのキー}: 確認ページに記載されているキー

さくらのクラウドでシンプル監視を作成

次にシンプル監視を作成します。Webhookの通知先として先ほど確認したURLを設定します。 シンプル監視の作成時に通知先としてWebhookを選択するとWebhook URLという入力欄が出てきますのでそこに入力します。

動かしてみる

あとは動かしてみましょう。

応用: Webhookのペイロードを使いたい場合は?

IFとTHENの間にフィルターを追加してコードを書く必要があります。

参考: Parsing JSON body with filter code

// シンプル監視から渡されるJSONのパース
let payload = JSON.parse(MakerWebhooks.jsonEvent.JsonPayload);

// パースした内容を利用する例(Slackへの投稿)
Slack.postToChannel.setMessage(payload.attachments[0].text);
Slack.postToChannel.setTitle(payload.attachments[0].title);

終わりに

まだZapierは試せてませんが、近いうちにそちらも試してみようかと思います。

以上です。

備忘録: TeamCityでGolangのテスト結果をリアルタイム表示する

忘れがちなTeamCityの設定についての備忘録です。

今回の設定内容: Golangのテスト結果をリアルタイム表示

Golangで書いたアプリをTeamCity上でCIする際にテスト結果をきれいに表示するようにします。

f:id:febc_yamamoto:20220212143412p:plain

設定手順

  • プロジェクト - ビルド機能(Build Features)でGolangを有効化
  • go test-jsonパラメータを追加

ビルド構成でGolangを有効化

まずは各プロジェクト/各ビルド構成でビルド機能(Build Features)の画面を開き、Golangを追加します。

f:id:febc_yamamoto:20220212142653p:plain

Add Build Featuresボタンから追加できます。

f:id:febc_yamamoto:20220212142729p:plain

go test-jsonパラメータを追加

次にテスト結果をJSONで出力するようにパラメータを追加します。 直接go testに追加しても良いですし、環境変数GOFLAGS-jsonを指定してもOKです。 (ただし両方指定するとエラーになるので注意)

実行

あとは該当ビルド構成をRunするだけです。

f:id:febc_yamamoto:20220212143412p:plain

Testsというタブが追加され、各テストの詳細が表示されていることが確認できるはずです。 普通にコンソール出力された文字列を追うよりわかりやすいですね。

ということで今回は以上です。

出典

pleiades.io

blog.jetbrains.com

AWSの料金をSlackに通知するLambdaをRustに移植してみた

はじめに

お仕事でAWS Lambdaを使って実装する処理が出てきました。
この処理はクリティカルな部分ではない、補助的な処理だったため日頃から使う機会を窺っていたRustで実装してみることにしました。

まずはRust+Lambdaの肩慣らしのために、プライベートなアカウントで利用している毎日のAWSの料金をSlackに通知する処理をRustに移植してみることにしました。

元ネタ: LambdaでAWSの料金を毎日Slackに通知する(Python3) qiita.com

今回移植したコード一式はこちらにおきました。 github.com

Rustへの移植

基本的には元のPythonの処理をそのまま移植していく方針としました。
関数の作成やIAMロールへのポリシーのアタッチなども元ネタとほぼ同じやり方にしています。

関数の作成はこんな感じでカスタムランタイムを選択しておきます。アーキテクチャx86_64にしました。

f:id:febc_yamamoto:20211216213606p:plain

コードはローカルでzipファイルを作ってアップロードする形にします。

f:id:febc_yamamoto:20211216213826p:plain

プロジェクト構成

全体的な構成はこんな感じにしました。

$ tree .
.
├── Cargo.lock
├── Cargo.toml
├── Makefile
├── bootstrap // エントリーポイント用のバイナリクレート
│   ├── Cargo.toml
│   └── src
│       └── main.rs
└── event.json // テスト用のダミーインプット

Lambdaのカスタムランタイムの仕様としてエントリーポイントはbootstrapという実行可能ファイルにする必要があるとのことでした。 docs.aws.amazon.com

今回はCargoのワークスペースを作成しその中にバイナリクレートとしてbootstrapというクレートを配置する形にしました。

ビルド〜zip作成

こちらに従ってビルドしていくようなMakefileを用意しました。

github.com

あらかじめrustup target add x86_64-unknown-linux-gnuしておいた上でmake zipするとDocker上でクロスコンパイル〜zip作成が行われるようになっています。 Makefileはこんな感じです。

DOCKER_PLATFORM ?= linux/amd64
RUST_VERSION    ?= 1.57
RUST_ARCH       ?= x86_64-unknown-linux-gnu
DEPS            ?= bootstrap/src/*.rs bootstrap/Cargo.toml Cargo.toml Cargo.lock

RELEASE_DIR     := ${PWD}/target/${RUST_ARCH}/release
TARGET_BIN      := ${RELEASE_DIR}/bootstrap
TARGET_ZIP      := lambda.zip

build:
  cargo build --release --target ${RUST_ARCH}

.PHONY: buildx
buildx: $(TARGET_BIN)

$(TARGET_BIN): $(DEPS)
  docker run -it --rm --platform ${DOCKER_PLATFORM} \
    -v "$${PWD}":/usr/src/myapp -w /usr/src/myapp rust:${RUST_VERSION} \
    make build
    
.PHONY: zip
zip:  $(TARGET_ZIP)
$(TARGET_ZIP): $(TARGET_BIN)
  zip -j "$(TARGET_ZIP)" "$(TARGET_BIN)"

PythonからRustへの移植

移植したコード全体はこちらです。 github.com

ロギング

pythonではloggerをこんな感じで用意していました。

logger = logging.getLogger()
logger.setLevel(logging.INFO)

print!println!でも良かったのですが、ログレベルをサポートするためにこちらを使うことにしました。

docs.rs docs.rs

こんな感じで使います。

// 初期化
simplelog::SimpleLogger::init(LevelFilter::Info, Config::default()).unwrap();

// ログ出力
log::info!("hello {}", "world");

AWS SDK

boto3の代わりにrusotoを使います。

github.com

⚠️ Rusoto is in maintenance mode. ⚠️と書かれてますが今回は気にせず使うことにしました。 こんな感じになります。

    let client = CloudWatchClient::new(Region::UsEast1);

    client.get_metric_statistics(GetMetricStatisticsInput {
        namespace: String::from("AWS/Billing"),
        metric_name: String::from("EstimatedCharges"),

        dimensions: Some(vec![Dimension {
            name: String::from("Currency"),
            value: String::from("USD"),
        }]),

        start_time: (Utc::today().and_hms(0, 0, 0) - Duration::days(1))
            .format("%+")
            .to_string(),
        end_time: Utc::today().and_hms(0, 0, 0).format("%+").to_string(),

        period: 86400,
        statistics: Some(vec![String::from("Maximum")]),
        ..GetMetricStatisticsInput::default()
    }).await

SlackへのPost(WebHook)

requestsの代わりにreqwestを使います。

docs.rs

こんな感じにになりました。

    let client = reqwest::Client::new();
    client.post(slack_post_url.to_string()).body(body.to_string()).send().await?;

実行!

ということでmake zipし、作成されるzipファイルをマネジメントコンソールからアップロードしテスト実行してみます。

f:id:febc_yamamoto:20211216214138p:plain

いい感じですね!

残課題

Dockerでのビルド周りが遅いのは要改善です。 また、LocalStackやlambci/lambdaを用いてローカル実行できるようにしてあげる必要もあると思います。

この辺は追々対応していきます。

ということで今回は以上です。

連携できるアプリは3000個以上!さくらのクラウド+iPaaS(Zapier)で広がる世界

f:id:febc_yamamoto:20211201153742p:plain

はじめに

最近Zapierを触る機会がありました。 これまでiPaaS的なことをやるときにIFTTTのPro版を使っていたのですが、Zapierを試してみるとなかなか使い勝手が良かったので試した内容を残しておきます。

Zapierとは

ZapierとはいわゆるiPaaSで、さまざまなWebアプリケーションを統合/自動化してくれます。

こちらの動画を見ると、カタカナだと「ザピアー」と読むのが近いですかね。
youtu.be

サポートしているappは3000を超えており、よく使うようなアプリ(GmailやTrello、Slack/Discord、スプレッドシートなど)にきちんと対応しています。

https://zapier.com/apps

対応していないアプリについては、アプリ側がWeb APIを提供していれば自分でIntegrationを作成することで対応させることができます。

zapier.com

IntegrationはGUI上でポチポチ(Zapier Platform UI) またはCLI経由で作成することが可能です。

platform.zapier.com

BASIC認証にも対応してますのでさくらのクラウドにも対応できそうです。

Zapier+さくらのクラウドで何ができるの?

Actions

ZapierからAPIを叩けますので、何かをトリガーにAPIを叩くことが可能です。
この記事では例としてDiscordに書き込んだらサーバを起動するという仕組みを作ってみます。

Triggers

また、ZapierにはAPIなどでデータをポーリングしてデータが追加/変更されたことを検知する仕組みが備わっています。 例えば

  • 新しいサーバが追加されたら何かをする
  • サーバの起動状態(起動 or シャットダウン)が変わったら何かをする
  • DNSレコードが追加されたら何かをする

みたいなことが可能です。 この記事ではサーバの起動状態が変わったことを検知してみます。

Actionsを試してみる

まず動きを理解しやすいActionsから取り組んでみます。
Actionとは何かしらのトリガー(Gmailでのメール受信とかSlackでのメッセージ受信とかWebhookとか)を受けた時に実行される処理の事です。 何かしらのトリガーを用意した上でさくらのクラウドAPIを呼ぶ処理を実装してみます。

トリガーの準備(Discord)

トリガーはなんでも良いのですが、今回は手軽に試せるようにDiscordの特定チャンネルに書き込みがあったら何かするようにしてみます。 Discordのサーバを用意し、専用のチャンネルを用意します。

参考: Discord: サーバ作成の仕方

今回チャンネル名はzapier_testとしました。

Integrationの作成

こちらからIntegrationの作成を開始します。 (アカウントがない場合は作っておいてください。無料プランでも問題ないです)

developer.zapier.com

NameやDescriptionなどを適当に入力していきます。 下の方のIntended AudienceRoleは以下のようにしてください。

  • Intended Audience: Private
  • Role: I have no affiliation with __

Intended Audienceは公開範囲です。Publicにしたい場合にはいくつかの条件をクリアする必要があります。(詳細はToSを要確認) Roleは統合対象のアプリ(今回はさくらのクラウド)との関係(雇用関係があるか?)です。作成対象のIntegrationを公式ディレクトリで公開したい場合に設定が必要です。
今回はI have no affiliation with __(無関係)を選びます。

Authenticationの作成

次にアクションで使う認証情報を指定します。この設定は後ほどトリガーでも利用可能です。
画面左のメニューからAuthenticationを選び、Basic Authを選択してから保存します。

次に認証情報のテスト用のURLを指定します。 さくらのクラウドには認証情報を確認するAPIが用意されていますのでこちらを利用します。

GET:https://secure.sakura.ad.jp/cloud/zone/is1a/api/cloud/1.1/auth-statusと入力して保存してください。

テスト用のAPIキーの登録

続いて認証情報のテストを行います。

まずはAPIキーを登録します。Sign in to ...というボタンをクリックするとポップアップ画面が表示されますのでさくらのクラウドAPIキーを入力します。

登録したらTest Authenticationをクリックして動作確認しておきます。

Actionの作成

次にアクションを作成します。 今回はサーバの電源をONにする処理を実装してみます。

左のメニューからActionsを選びAdd Actionボタンから新規作成画面を開きます。 Settingsタブは以下のように入力します。

f:id:febc_yamamoto:20211201140949p:plain

入力後は一度保存してください。

Inputs

次にInput Designerタブでこのアクションを実行するのに必要な入力項目(Input)を指定していきます。
今回は操作対象のサーバが属するゾーンとサーバのIDを指定可能にします。
手作業で入力すると大変なので、ゾーンとサーバをドロップボックスで選べるようにします。
こんな感じの動きになります。

Zone

まずはZoneを追加します。Input Fieldを追加します。

KeyとLabelにはZoneと入力してください

Dropdown Sourceには以下のJSONを入力します。

[
  {
    "sample": "is1a",
    "value": "is1a",
    "label": "石狩第1ゾーン"
  },
  {
    "sample": "is1b",
    "value": "is1b",
    "label": "石狩第2ゾーン"
  },
  {
    "sample": "tk1a",
    "value": "tk1a",
    "label": "東京第1ゾーン"
  },
  {
    "sample": "tk1b",
    "value": "tk1b",
    "label": "東京第2ゾーン"
  },
  {
    "sample": "tk1v",
    "value": "tk1v",
    "label": "Sandbox"
  }
]

サーバのID

次にサーバのIDを指定可能にします。 Dynamic Fieldを追加し、コードは以下をコピペします。

const options = {
  url: 'https://secure.sakura.ad.jp/cloud/zone/{{bundle.inputData.Zone}}/api/cloud/1.1/server',
  method: 'GET'
}

return z.request(options)
  .then((response) => {
    response.throwForStatus();
    const results = response.json;

    return { 
      key: 'ServerID', 
      label: "ServerID",
      required: true,
      choices: results.Servers.map(v => {
        return { label: v.Name , sample: v.Name, value: v.ID }
      })
    }
  });

{{bundle.inputData.Zone}}で前に指定したZoneのinputの値を参照できます。
その後APIの戻り値からZapierが理解できる形に変換して返しています。 参考: How to add Dynamic and Custom Fields

API設定

さくらのクラウドAPIを呼ぶ設定をしていきます。 API Configurationタブを開きStep1に入力していきます。 以下のように入力してください。

  • メソッド: PUT
  • URL: https://secure.sakura.ad.jp/cloud/zone/{{bundle.inputData.Zone}}/api/cloud/1.1/server/{{bundle.inputData.ServerID}}/power

先ほども出てきた{{...}}という記法でInputを参照してURLを組み立てます。

保存したらStep2でテストしてみます。

API設定のテスト

Configure Test Dataでは定義しておいたInputを入力できるのですが、Dynamic Fieldにはうまく対応していないためRawを選んで直接入力します。 以下のJSONを入力します。(ゾーンとIDは各自の値に置き換えてください)

{
  "inputData": {
    "Zone": "is1a",
    "ServerID": "111111111111"
  }
}

うまくいけば以下の表示が出るはずです。

f:id:febc_yamamoto:20211201145057p:plain

Integrationを試す

これでActionが出来ましたのでIntegrationを試してみましょう。 ダッシュボードからCreate Zapボタンを押しましょう。

zapier.com

画面左上の入力欄でZap名を指定し、App EventではDiscordを検索して選択します。

Discordトリガーの設定

次にTrigger TypeをNew Message Posted to Channelにします。

次にDiscordにサインインするように促されます(初回のみ)

Discord側で権限の確認画面が出ますのでサーバを間違えないように選択してから許可を出します。

次に対象のチャンネルを選択します。

作成したActionの設定

次に作成したActionの設定を行います。 App Eventに作成したアクションの名前を入れて検索&選択します。

Eventとして先ほど作成したActionが選べるはずです。

Actionを選んだらパラメータを指定します。 Zoneを選んだら該当ゾーンにあるサーバがドロップダウンで選択できるようになります。

テストはスキップしても構いませんしここでテストしてもOKです。

最後にTurn on ZapをクリックしてZapを有効化しておきます。

動作確認

最後に動作確認してみます。Discordの指定チャンネルになんでも良いので書き込みしてみます。 サーバが起動したら成功です!

お好みでサーバ起動後に通知を出したり、Discordで任意の文字列が書き込まれたら起動するように修正するとグッと実用的になるかと思います。

例: Discordからの書き込み内に起動という文字が存在している場合だけ処理するようにフィルターを設定

Triggersでさくらのクラウド上のリソースの変更を検知してみる

続いてTriggersを試してみます。

ZapierのTriggers

Zapierは以下2つのトリガーをサポートしています。

  • REST Hook Trigger
  • Polling Trigger

REST Hook Trigger

REST Hook Triggerは統合対象のアプリケーションの側から通知をしてもらう方式です。
統合対象のアプリケーション側でデータが増えたり更新された時にZapierに通知することで即時トリガーすることが可能です。
ただし、統合対象のアプリケーション側がREST Hooksに対応している必要があります。

残念ながらさくらのクラウドはREST Hooksに対応していませんので次のPolling Triggerを使用する必要があります。

Polling Trigger

Polling Triggerはその名の通りポーリングでデータの追加/更新を検知する方式です。
統合対象からAPIでデータを定期的に取得し、追加や更新があったかをZapier側で判断してトリガーしてくれます。

ただし、APIでデータを取得する際にデータをZapierが理解できる形に変換しておく必要があります。 platform.zapier.com

具体的には、

  • 配列
  • 各要素はidというフィールドを持つオブジェクト
  • 作成/更新時間の逆順でソートされていること(新しいデータがより前にあること)

という形式である必要があります。

例:

[
  { id: 2, name: "example2"},
  { id: 1, name: "example1"}
]

例えば1回目のAPIコールで上記のデータを返したとします。Zapierはこれを保持しており、次回リクエスト時の結果と比較して追加/変更を検知してくれます。

例:

[
  { id: 3, name: "example3"},
  { id: 2, name: "example2"},
  { id: 1, name: "example1"}
]

というデータが来たらid:3のデータでトリガーしてくれます。

詳細はこちらを参照してください。 zapier.com

ということで実際にPolling Triggerを作成していきます。

Polling Triggerの作成

では例としてサーバの起動状態が変わったことを検知するPolling Triggerを作成してみます。

まずこんな感じで基本的な項目を入力します。

次にInputは先ほど作ったActionと同じようにZoneを追加しておきます。

API Configuration

次にAPI Configurationです。 ここではAPIでデータを取得した後Zapierが理解できる形にデータを変換します。
コードを用いるため、Switch to Code Modeボタンを押してコード入力モードに切り替え、以下のコードを入力します。

const options = {
  url: `https://secure.sakura.ad.jp/cloud/zone/${bundle.inputData.Zone}/api/cloud/1.1/server`,
  method: 'GET'
}

return z.request(options)
  .then((response) => {
    response.throwForStatus();
    const results = response.json;

    return results.Servers.map( (v) => {
      v.originalId = v.ID;
      v.id = z.hash('md5', v.ID + v.Instance.StatusChangedAt);
      return v;
    });
  });

ポイントは以下の部分です。

return results.Servers.map( (v) => {
      v.originalId = v.ID;
      v.id = z.hash('md5', v.ID + v.Instance.StatusChangedAt);
      return v;
    });

APIからの戻り値のIDフィールドと、起動状態が最後に変わった日時を保持しているフィールドInstance.StatusChangedAtを結合した値からハッシュを算出してidにしています。
こうすることでサーバの起動状態が変わったらidが変更されZapierから変更を検知できるようになります。

あとはActionの時と同じでテストを行い保存しておきます。

Zapを作成して動作確認

ではIntegrationを使ってみます。 今回はサーバの起動状態が変わったらDiscordの特定チャンネルにメッセージを投稿してみます。

Triggerの選択〜編集

Zapの作成画面を開き、Zap名を入力、作成したIntegrationの名前を入力して検索&選択してください。

トリガーとして先ほど作成したものが選択できるようになっているはずです。

アカウント選択〜ゾーンの選択を行いテストまでしておきましょう。 うまくいけばこんな画面が表示されます。

Actionの選択〜編集

次にDiscordの特定チャンネルにメッセージを送るためのアクションを設定します。 Discordを選択し、Action EventとしてSend Channel Messageを選択します。

次に送信先チャンネルの選択やメッセージの設定を行います。 メッセージ本文にはTriggerが取得したサーバの情報が利用可能です。

いい感じに設定しましょう。

投稿するBotの名前やアイコンも変更できますのでお好みで変更してみてください。

あとはTurn on Zapをクリックして有効化しましょう!

動作確認

それではサーバの起動状態を変えるためにシャットダウンしたり起動したりしてみましょう。 うまくいけばDiscordにこんな感じのメッセージが届くはずです。

f:id:febc_yamamoto:20211201181214p:plain

良さそうですね!!

ポーリングの間隔は?

ポーリングの間隔はプランごとに決まっているようです。 f:id:febc_yamamoto:20211201182311p:plain

Free/Starterプランで15分ごと、Professionalプランで2分ごと、Team/Companyプランで毎分となっています。
用途に合わせて適切なプランを選びましょう。 (個人的にはProfessionalがもうちょっと安くなってくれれば、、、と感じてます)

まとめ

ということで今回はZapierとさくらのクラウドを組み合わせてみました。
日々の運用に、レポート作成にと様々な用途で利用できるかと思います。夢が広がりますね!

ただIntegrationの作成で若干のコードを書かないといけないのが不満です。
これはさくらのクラウド向けPublic Integrationを作成して公開すると解決できそうです。

例えばDigitalOceanであればこんな形でPublic Integrationが公開されておりすぐに利用できるようになっています。 zapier.com

今はこの記事で試したことをベースにCLIによるIntegrationの作成を試してみているところですので、それが上手くいったら公開したいと思っています。
何とか今年中には公開したいですね。開発を頑張ります…

ということでZapier+さくらのクラウドはなかなかに便利だと思いますので是非お試しくださいー!

以上です。

おまけ: 他のiPaaS的なもの

今回の記事を書くにあたりZapier以外のいくつかのiPaaS(的なものも含む)でもさくらのクラウドAPIを使って連携できるか試してみました。

IFTTTはAPIをポーリングして変更を検知というのが難しかったです(結構ガッツリとコード書く必要がありそう)。
またWorkatoについては最終的なお値段は問い合わせないとわからないということだったので途中で試すのをやめちゃいました(なかなかいいお値段との情報もちらほら…)。

残るPower Automateやn8n.ioはそれぞれZapierとは違った魅力を感じました。
Zapierだと結構いいお値段ですので、割と手軽なお値段のPower Automateやオンプレにも立てられるn8n.ioは環境/状況次第では選択肢になりそうでした。
この辺についてはまた機会があれば記事にしようかと思っています。

最後のRed Hat Fuse Online/Syndesisについてですが、個人的にはApache Camel大好きなので是非試したかったところなのですが時間がなくて今回は試せませんでした。また時間を見つけてチャレンジしてみるつもりです。

それでは今度こそ以上です。

さくらの専用サーバPHYのAPIをGoから使う sacloud/phy-go

リリースしました。

github.com

なにこれ?

さくらの専用サーバPHYは一部の操作をAPIから行えるようになっています。

manual.sakura.ad.jp

APIはOpenAPI 3.0で記述されたAPI定義が公開されており、コードジェネレータさえ対応していればお好きなプログラミング言語から手軽に利用できるようになっています。

sacloud/phy-goはAPI定義から生成されたコードをラップし、より簡素な記述ができるようにしたものです。
Exponential Backoffなリトライやレスポンスのトレースログ出力といった便利機能も持ってます。

どんな感じで使うの?

サーバのACPIシャットダウンを行うコードを例に、API定義から生成したコードをそのまま使う方法とsacloud/phy-goを使う方法を比較してみます。

生成したコードをそのまま使う場合

   result, err := client.PostServersServerIdPowerControlWithResponse(
        context.Background(),
        serverId,
        &PostServersServerIdPowerControlParams{
            XRequestedWith: "XMLHttpRequest",
        },
        PostServersServerIdPowerControlJSONRequestBody{
            Operation: "soft", // ACPIシャットダウン
        })
    if err != nil {
        return err
    }
    if result.StatusCode() == http.StatusNoContent {
        // ...
    }

sacloud/phy-goを使う場合

   if err := phy.NewServerOp(client).PowerControl(ctx, serverId, v1.ServerPowerOperationsSoft); err != nil {
        return err
    }

より簡潔に書けるようになってると思います。

PHYのAPIを使う上での注意点

専用サーバPHYのAPIにはレートリミットが設けられています。
https://manual.sakura.ad.jp/ds/phy/api/api-spec.html#section/基本的な使い方/API(Rate-Limiting)

  • 基本はご利用の アカウントごとに300リクエスト/1時間 まで
  • サーバーのネットワーク設定を行うエンドポイントは、 サーバーごとに5リクエスト/5分間 まで

あまりAPIを使いすぎると429エラーになってしまいます。

sacloud/phy-goにはFakeサーバが同梱されていますので開発中はこちらを利用しましょう。 利用方法はsacloud/phy-goのREADME.mdを参照してください。

終わりに

ということでGoからPHYのAPIを使う際はsacloud/phy-goを是非ご利用ください。 以上です。