LoginSignup
1
0

More than 1 year has passed since last update.

IBM Cloud FunctionsをElixirで

Last updated at Posted at 2021-04-30

はじめに

※使用ライブラリを、AWS Lambda, Azure Functions, IBM Cloud Functionsで使える共通ライブラリにしたので、記事を若干修正しました。(2021/07/07)

AWS Lambda、Azure Functionsに続き、今回、IBM Cloud FunctionsのアプリケーションをElixirで簡単に実装できるライブラリを作ってみたので、それを使ってIBM Cloud Functionsへのデプロイまでをやってみたいと思います。

ライブラリはこちらで公開
→ https://github.com/imahiro-t/faas_base
→ https://hex.pm/packages/faas_base

以前の投稿
Azure FunctionsをElixirで
ElixirでAWS LambdaでGithubActionsで継続デプロイ

ElixirでIBM Cloud Functions

IBM Cloud FunctionsはApache OpenWhiskというサーバレス基盤のオープンソース(と言ってもIBMが主体となって進めていたもの)に準拠していて、現時点でElixir用のライブラリは用意されてはいませんが、それ以外の言語であっても、CLIアプリケーションのようなバイナリを用意してあげることでDockerイメージとして動作させることができるようです。

この辺りについては作成したライブラリ側で吸収しているので、今回はこの辺りをあまり意識せずにデプロイまでやっていくことになります。

やってみる

IBM Cloud CLIのセットアップ

IBM Cloudをターミナルからデプロイしたりできるツールです。こちらの手順に従ってセットアップします。

続いて、下記コマンドでCloud Functions CLIプラグインのセットアップを行います。

$ ibmcloud plugin install cloud-functions

IBM Cloud Functions環境の作成

下記コマンドでIBM Cloud Functionsをデプロイする名前空間を作成・設定します。

$ ibmcloud fn namespace create my_namespace
$ ibmcloud fn property set --namespace my_namespace

アプリケーション作成

まずはmix new upcaseとプロジェクトを作成し、mix.exsにIBM Cloud Functions用のライブラリを追加します。

  defp deps do
    [
      {:faas_base, "~> 1.0.2"}
    ]
  end
$ mix deps.get

次にupcase.exに下記のようにハンドラを実装します。(サンプルとして小文字を大文字にするだけの簡単な関数アプリです)

defmodule Upcase do
  use FaasBase, service: :ibm
  alias FaasBase.Logger
  alias FaasBase.Ibm.Request
  alias FaasBase.Ibm.Response
  @impl FaasBase
  def init(context) do
    {:ok, context}
  end
  @impl FaasBase
  def handle(%Request{body: body} = request, event, context) do
    Logger.info(request)
    Logger.info(event)
    Logger.info(context)
    {:ok, Response.to_response(body |> String.upcase, %{}, 200)}
  end
end

IBM Cloud Functionsのランタイムからはリクエスト情報が格納されたeventと環境変数等の情報が格納されたcontextがMap型で渡ってきます。

第一引数のrequestにはevent情報のbodyやらheadersやらmethodやらを扱いやすいように展開して格納しています。

戻り値は{:ok, String.t}か{:error, String.t}のように文字列のみを返すか、{:ok, FaasBase.Ibm.Response.t}か{:error, FaasBase.Ibm.Response.t}のようにヘッダー情報やステータスコードを含めた情報を返す必要があります。

試しにコンソールでハンドラの動作確認をしてみます。

$ iex -S mix
iex> alias FaasBase.Ibm.Request
iex> Upcase.handle(%Request{body: %{"data" => "hello"}}, %{}, %{})
{:ok,
 %FaasBase.Ibm.Response{
   body: "{\"DATA\":\"HELLO\"}",
   headers: %{},
   status_code: 200
 }}

問題なさげです。

デプロイ

IBM Cloud Functionsの実行環境はLinuxになるので、ビルドは、Linux上で行う必要があります。ライブラリには、ビルド用のmixタスクが用意されていて、こちらを実行すると、ビルドとともに、にデプロイに必要なzipファイルが作られます。

$ handle_module=Upcase
$ mkdir -p _build
$ docker run -d -it --rm --name elx erintheblack/elixir-ibm-functions-builder:1.10.4
$ docker cp lib elx:/tmp
$ docker cp mix.exs elx:/tmp
$ docker exec elx /bin/sh -c "mix deps.get; MIX_ENV=prod mix ibm.release ${handle_module}"
$ docker cp elx:/tmp/_ibm ./_build
$ docker stop elx

下記コマンドでWEBアクションとしてデプロイします。

$ cd ./_build/_azure
$ ibmcloud fn action create upcase upcase-0.1.0.zip --native --web true --param LOG_LEVEL info

エンドポイントは下記コマンドで取得できます。

$ ibmcloud fn action get upcase --url

ok: got action upcase
https://us-south.functions.appdomain.cloud/api/v1/web/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/default/upcase

動作確認

curlで叩いて正常に動作することを確認します。

$ curl -H "Content-Type: application/json" https://us-south.functions.appdomain.cloud/api/v1/web/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/default/upcase -d '{"data": "hello"}'

{"DATA":"HELLO"}I

さいごに

FaaSのElixirのライブラリ作成は今回で3つ目ですが、毎回異なるアプローチでカスタム言語に対応した基盤が作られている感じがします。

今回特徴的だったのが、毎回出力して終了するCLIのようなアプリを作成するというもので、Azure Functionsと同様に簡単にWEBからのリクエストが受けられるとは言え、Elixirで書けるからという理由だけで選択するには、かなりシチュエーションを選ぶ気がします。

また、現状では環境変数がこちらから設定できないみたいで、デプロイ時にパラメータとしての設定は可能ですが、リクエスト時にPOSTデータと混在して渡されるなど、使い勝手も。。。な感じでした。

デプロイ時のフラグに--web-secure trueを付けるだけで、リクエストヘッダーにセキュアな値設定を必須にできるなど、痒いところに手が届く機能もあるようなので、オープンソースを活かし今後どんどん使い勝手が良くなっていくかもです。

残るはIBMじゃない方のCloud Functionsですが、こちらはまだカスタム言語に対応していないみたいです。対応予定はあるのかな。。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0