IBM Cloud Functions を Swift で使う【実践編】

以前、IBM Cloud Functions の Hello World を Swift でやってみました.

今回は IBM Cloud Functions をより実践的な観点で使ってみました.

実装環境

  1. macOS High Sierra 10.13.2
  2. Docker for Mac 17.12.0
  3. Xcode 9.4
  4. Swift 4.1

 

パッケージ導入

実戦的に使う上でまず気になるのはパッケージの導入でしょうか.
大丈夫です、Functions でも外部パッケージを導入できます.

GitHub に外部パッケージを含めるビルド手順が記載されています.

必要なのは以下の手順です.

  • ビルドスクリプト(compile.sh) を作成する(コピペでOK)
  • 利用パッケージ一覧(Package.swift) を作成する
  • メイン関数(main.swift) を作成する
  • ビルドする

ディレクトリ構成は以下のようになります.

今回は NoSQL DB である Cloudant の Swift SDK を使ってみたいと思います.

対応する Package.swift は以下のようになります.

// swift-tools-version:4.0
import PackageDescription

let package = Package(
    name: "Action",
    products: [
      .executable(
        name: "Action",
        targets:  ["Action"]
      )
    ],
    dependencies: [
      .package(url: "https://github.com/cloudant/swift-cloudant.git", .upToNextMajor(from: "0.8.0"))
    ],
    targets: [
      .target(
        name: "Action",
        dependencies: ["SwiftCloudant"],
        path: "."
      )
    ]
)

 

メイン関数

Functions の実際の処理となるメイン関数です.

import Foundation
import SwiftCloudant

func main(args: [String:Any]) -> [String:Any] {
    // Create a CouchDBClient
    let cloudantURL = URL(string:"https://XXXX-bluemix.cloudant.com")!
    let client = CouchDBClient(url:cloudantURL, username:"XXXX-bluemix", password:"XXXXd8d8816d7a7ca")
    let dbName = "transaction"
    var _error : Error?
    var _response : [String : Any]?
    
    // Read a document
    let read = GetDocumentOperation(id: "XXXX", databaseName: dbName) { (response, httpInfo, error) in
        if let error = error {
            _error = error
        } else {
            _response = response
        }
    }
    
    client.add(operation:read)

    // Wait for Cloudant's response
    while true {
        usleep(100)
        if (_error != nil || _response != nil) {
            break
        }
    }
    
    // Return response
    if _response != nil {
        print("response ... \(_response)")
        return _response!
    } else {
        print("error ... \(_error)")
        return (["error":"\(_error)"])
    }
}

JSON を返す Action になるので返り値は [String:Any] になります.

また、print(“…”) は Logs として JSON 形式で Functions 上に出力されます.

[
“2018-06-17T04:58:16.361178453Z stdout: response … Optional([\”_rev\”: \”1-XXXX\”, \”pageId\”: 21, \”_id\”: \”XXXX\”, \”dateTimeLocal\”: \”2017-10-22T01:48:42.849+09:00[Asia/Tokyo]\”, \”pageName\”: \”MF-Overview\”])”,
“2018-06-17T04:58:16.361148831Z stderr: 2018-06-17 04:58:16.155 Action[11:2ae60700] Cookie request successful”
]

 

ビルド&デプロイ

ソースコードが用意できましたらいよいよビルド&デプロイです.

まずはソースコードをビルドします.

compile.sh を実行します.
第一引数にソースコードが配置されているディレクトリ名を、第二引数に Swift のバージョンを設定します.

以下、実行結果です.

functions $ bash compile.sh hello swift:4.1
+ ‘[‘ -z hello ‘]’
+ ‘[‘ -z swift:4.1 ‘]’
+ OUTPUT_DIR=build
+ ‘[‘ swift:4.1 == swift:3.1.1 ‘]’
+ ‘[‘ swift:4.1 == swift:4.1 ‘]’
+ RUNTIME=openwhisk/action-swift-v4.1
+ BASE_PATH=/swift4Action
+ DEST_SOURCE=//swift4Action/spm-build/Sources/Action
+ DEST_PACKAGE_SWIFT=/swift4Action/spm-build/Package.swift
+ BUILD_FLAGS=
+ ‘[‘ -n ” ‘]’
+ echo ‘Using runtime openwhisk/action-swift-v4.1 to compile swift’
Using runtime openwhisk/action-swift-v4.1 to compile swift
++ pwd
+ docker run –rm –name=compile-ow-swift -it -v /Users/DaikiKawanuma/Desktop/functions:/owexec openwhisk/action-swift-v4.1 bash -ex -c ‘

Linking ./.build/x86_64-unknown-linux/release/Action
+ echo ‘Creating archive hello.zip…’
Creating archive hello.zip…
+ mkdir -p /owexec/build
+ zip /owexec/build/hello.zip .build/release/Action
adding: .build/release/Action (deflated 73%)

 

次にデプロイです.

Blumix CLI をインストールし、Cloud Functions プラグインを導入します.
以下の手順をご参照ください.

デプロイコマンドを実行します.

functions $ bx wsk action update helloworld build/hello.zip –kind swift:4.1
ok: updated action helloworld

これで作成手順は完了です.

 

実装結果

Functions のダッシュボート上で Invoke してみます.

 

実行結果です.

DB アクセス込みで 1,000ms 程度であればまずまずではないでしょうか.

 

まとめ

今回は IBM Cloud Functions を Swift で、より実践的な観点で使ってみました.

以下の点は実運用上で利点になるかと思います.

  • 外部のパッケージを利用できる
  • パッケージをコードで管理できる(Package.swift)
  • ビルド・デプロイがコマンドで実行できるため CI/CD に組み込める

Swift を使える Functions はあまり無いと思うのでぜひ使ってみていただければと思います.
Enjoy サーバーサイド Swift!(サーバーレスだけど)

以上です.

PS. 情報提供いただいた @taiponrock さんありがとうございましたorz