【BTP】SAP Feature Flags Serviceを使ってみた

この記事は [SAP Advent Calendar 2021](https://adventar.org/calendars/6252) の12月10日分の記事として執筆しています。

# はじめに

今回、SAP BTP Trialで利用できるサービスのなかからSAP Feature Flags Serviceを使ってみました。
Help Portalのドキュメントは[こちら](https://help.sap.com/viewer/2250efa12769480299a1acd282b615cf/Cloud/en-US/d485374a71a149a7ba96b7403985a1a6.html)

## Feature Flagとは？
> アプリケーションを再デプロイまたは再起動せずに新しい機能を有効または無効にできます。

とあるように、「コードを書き換えることなく動的にシステムの振る舞いを変更できる」開発手法です。
アプリケーションの外部にフラグを持つことで機能のON/OFFを切り替えることができます。

あらかじめアプリケーションからFeature Flagの状態を参照することで下図のActiveボタンを切り替えるのみで動作の変更をできるようにします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159467/8593458e-eda0-be2d-7772-ea9cbb2ca0d6.png)

このFeature Flagがどのように活用できるか？は[こちら](https://codezine.jp/article/detail/14114)が参考になりました。

# SAP Feature Flags Serviceを使ってみる

## サービスインスタンスの作成
SAP BTP Trialで実際にSAP Feature Flags Service使ってみます

Service MarketplaceからFeature Flagsのサービスインスタンスを作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159467/46887722-395a-c10d-0807-f489fe42a9d6.png)

今回Planはstandardを選択しています。

※2021/12時点でliteプランも選択可能です。
　liteプランだと使用できるのはBoolean型のフラグのみとなりますが、
　フラグのON/OFFを自由に変更可能です。
　テスト用途ではliteプランを選択したほうが便利でした。

1ページ目以外は未指定のままCreateを押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159467/27a78506-9c5d-a56b-616f-abb443519379.png)

Createが完了したらサービスインスタンスにアクセスします。
左側メニューの「Instances and Subscriptions」からCreateしたインスタンスを確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159467/221aeb22-cdc2-b8fb-536c-efddb88ef498.png)

メニューから「View Dashboard」を押下します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159467/d841c4c1-2fe3-c225-e29b-c7519ade8fdf.png)

Feature Flags Serviceのダッシュボード画面が開くので、ここFeature Flagを作成していきます。
※認証方式を聞かれる場合はdefaultのIdpを選択してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159467/7519f93b-7d6b-a6ec-b519-2c0d2df9d9bb.png)

## Feature Flagの作成

とりあえず、「New Flag」を押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159467/e4b9bba6-58a7-fa6e-8609-397f8c2edbe8.png)

フラグ作成画面へと遷移します。
作成できるフラグはBooleanとStringがあります。
※liteプランはBooleanのみ
まずはBoolean型のフラグを作成してみます。
 `Name` `Description` を指定して「Save」を押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159467/7d866bee-5b3d-b5d7-894b-2197b7f54cd5.png)

フラグが作成できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159467/c75c9f26-ed77-8047-f4e8-d7e4725edc5e.png)

フラグを作れたけれどこれからどうするのかと思ったら
フラグのリンクを押下すると詳細に遷移でき、詳細メニューにCode Snippetsがあります。
Code Snippetにしたがって、今回はNode.jsでFeature Flagの状態を確認するAPIを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159467/f21f7535-3c53-31f2-8f98-33ac86e3fcea.png)


## Feature Flagを参照するAPIを作成する

> // get URI for Feature Flags service instance from VCAP_SERVICES

Code Snippetの上記記載からURI・username・passwordを取得する必要があるということなので、まずはFeature Flags ServiceのインスタンスにBindするNodejsアプリケーションを作成します。

以下を参考にシンプルなNodejsアプリケーションを作成し、デプロイしました。
https://developers.sap.com/group.scp-5-node.html

```javascript
const express = require('express');
const app = express();

app.get('/', function (req, res) {
  res.send('Hello World!');
});

const port = process.env.PORT || 3000;
app.listen(port, function () {
  console.log('myapp listening on port ' + port);
});
```
上記の通り、アクセスすると"Hello World!"を返却するAPIをデプロイします。
「demoNode」という名称でBTP上に作成しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159467/09bc6173-d229-b8bd-bed7-c447d9203ac9.png)

再び「Instances and Subscriptions」からサービスインスタンスにアクセスします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159467/9b5487ba-23f8-6f31-f53e-361127781bba.png)

「Bound Applications」の「Create」を押下し、先ほど作成したNodejsのアプリケーションに対してBindします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159467/8dd83ef7-83f7-fbf9-1654-9ffc9d79c7f3.png)


Createが終了すると、認証情報が表示できるのでこれらを使ってNodejsのアプリケーションからSAP Feature Flags Serviceに作成したフラグにアクセスします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159467/5e5d1412-24e5-5905-09e9-7b2f0aa3797a.png)

Code Snippetsを参考に、Feature Flagの状態を取得するAPIを作成しました。

```javascript
const express = require('express');
const request = require('request');
const app = express();

let uri = "<上記で作成した認証情報のUri>" ; // get URI for Feature Flags service instance from VCAP_SERVICES
let username = "<上記で作成した認証情報のUserName>" ; // get username for Feature Flags service instance from VCAP_SERVICES
let password = "<上記で作成した認証情報のPassWord>" ; // get password for Feature Flags service instance from VCAP_SERVICES
let feature = "demoflagboolean"; // the name of the feature flag as defined in the feature flags dashboard
let evaluationUri = uri + "/api/v1/evaluate/" + feature;
//let evaluationUri = uri + "/api/v1/evaluate/" + feature + "?identifier=<tenant_ID>"; // in case of direct shipment flags, identifier is mandatory

let authorization = "Basic " + Buffer.from(username + ':' + password).toString('base64');

app.get('/feature', function (req, res) {
    let bFeature;
    request.get({
        url: evaluationUri,
        headers: {
            "Authorization": authorization
        }
    }, function(error, response, body) {
        if (error) {
            // handle error
            res.send(error)
        }
        let statusCode = response.statusCode;
        switch (statusCode) {
            case 200: // active
                // logic when the flag is active
                bFeature = true
                break;
            case 204: // inactive
                bFeature = false
                break;
            default:
                // logic when the flag is inactive
                bFeature = false
                break;
        }
        res.send({feature:bFeature})
        
    });
  });

app.get('/', function (req, res) {
  res.send('Hello World!');
});

const port = process.env.PORT || 8080;
app.listen(port, function () {
  console.log('myapp listening on port ' + port);
});
```

フラグがTRUE=activeであればHTTPステータスコードが200、
FALSE=inactiveであればHTTPステータスコードが204で返却されます。

上記のコードをデプロイし、`/feature` にアクセスすると以下の結果が返却されます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159467/b8b3f676-799b-ead6-d287-caaa300b3fd7.png)

アクセス時点ではFeature FlagがInactive状態なので、HTTPステータスコードが204となっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159467/b764e966-a2b6-e982-2d67-ff8cefafe9bc.png)


## Feature Flagの変更

次にFeature Flagを変更してみます。
「Active」を変更してから、詳細へ遷移します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159467/6e8ca1d4-df8c-4e7f-a2c3-f73ea074e77a.png)

「Not Release」のステータスになっているので、「Release」ボタンを押下します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159467/72e6abd5-abaf-67c8-b836-a7fc689c6ded.png)


Release Featureを「Var.2」=TRUEに変更します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159467/57797039-a362-998b-78b4-143f69eb77c8.png)![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159467/c3d2ef98-3e67-4f85-d054-759ffbd5789f.png)

「Release」を押下するとFlagが変更されます。
**※一度Releaseすると変更不可です※**
※liteプランの場合、Release工程が存在せず何度でも変更可能です。

もう一度、Nodejsのアプリケーションへアクセスします。
Feature Flagの変更が適用され、下記の通りHTTPステータスが200へ変更されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159467/df164072-242a-2f20-850f-62b0e22c38a6.png)

# おわりに
Feature Flags Serviceを利用することでリリースすることなくシステムの挙動を変更できます。
またフラグ設定にはDirect DeliveryやPercentage Deliveryといった機能もあり、「特定のグループはフラグをONにする」といった使い方も可能です。

アプリケーションに組み込む必要があり、導入コストはそれなりに大きいことやうまく使わないとFeature Flag自体の管理が難しそうといった感覚もありますが開発手法・システムによっては非常に有用かと思います。