2022年5月18日水曜日

Oracle Cloudの通知を使うAPEXアプリケーションを作成する

 Oracle CloudのDevOpsサービスを使ってみようとしたところ、プロジェクトの作成には通知サービスのトピックが必要でした。通知のトピックは簡単に作れますが、それだけだと面白味がないので、作成したトピックにSlackのサブスクリプションを作成し、APEXアプリケーションからメッセージを送信(英語でPublishなので公開と翻訳されています)してみました。

以下のような動作になります。


通知の作成については、Todd Sharpさんによる以下の記事を参考にしています。

Oracle Cloud Notifications サービスを使ってみよう
https://blogs.oracle.com/otnjp/post/en_article_08

APEXアプリケーションからSlackに通知する方法は、以前にこちらの記事に記載しています。今回もIncoming Webhookを使用します。

気になる費用ですが、Oracle Cloud Infrastructure NotificationsサービスのFAQより確認しました。

Notificationsに無償枠はありますか?
Notificationsでは、Oracle Cloud Infrastructureのお客様が無償で開始できるように無償枠が導入されています。お客様は、1か月あたり100万件のHTTPSエンドポイントへのメッセージと1,000件のメール・メッセージを無償で配信することができます。

メール・メッセージはともかく、人によるアプリケーションの操作でHTTPSの無償枠を超えることはなさそうです。

では、以下よりアプリケーションを作成するために実施した作業を紹介します。


SlackチャンネルとWebhookの作成



OCIのトピックサブスクリプションとして作成する、SlackのIncoming Webhookを取得します。

最初にチャンネルを作成します。

Slackのクライアントより、チャンネルを作成するを実行します。


チャンネル名前説明を入力し、作成を実行します。今回はチャンネルの名前をtest-oci-notifとしました。


チャンネルの作成者は、デフォルトでユーザーとして追加されます。今のところ、他のユーザーを追加する必要はないため、後でするをクリックします。


チャンネル#test-oci-notifが作成されます。チャンネル名をクリックして、チャンネルの詳細を開きます。

インテグレーションのタブを開き、アプリを追加するを実行します。


検索ボックスにIncoming Webhooksと入力します。Incoming WebhooksがAppディレクトリに現れるので、インストールを実行します。


ブラウザにIncoming Webhooksの説明が表示されます。Incoming Webhooksを使ったインテグレーションは非推奨と記述されています。現在の推奨はchat.postMessageのようですが、Oracle Cloudのサブスクリプションとして登録できるのは、Incoming Webhooksのなので、Slackに追加を実行します。


チャンネルとして先ほど作成した#test-oci-notifを選択し、Incoming Webhookインテグレーションの追加を実行します。


チャンネル#test-oci-notifIncoming Webhookが作成されました。


画面下にIncoming Webhookに関する設定があります。Webhook URLをコピーし、後で利用できるようにどこかに記録しておきます。説明ラベル名前アイコンなどをカスタマイズして、設定を保存します。


以上で、SlackのIncoming Webhookの準備は完了です。


通知サービスのトピックとサブスクリプションの作成



OCIコンソール開発者サービスに含まれる、アプリケーション統合通知を開きます。


最初にトピックを作成します。Free Tierアカウントを使っていることもあり、コンパートメントは作成せず、ルート・コンパートメントに作成します。

トピックの作成を実行します。


トピックの名前をSlackのチャンネル名と同じtest-oci-notifとします(別の名前でも問題ありません)。説明に通知のテストと入力します。

作成をクリックします。


トピックはすぐに作成されます。作成されたトピックtest-oci-notifを開き、サブスクリプションを作成します。


リソースサブスクリプションを選択し、サブスクリプションの作成を実行します。


画面右にドロワーが開きます。プロトコルとしてSlackを選択し、URLに先ほど作成したWebhook URLを入力します。

作成をクリックします。


Slackのチャンネルに、以下のようなサブスクリプションの確認を求める通知が送信されます。URLのリンクをクリックし、サブスクリプションの作成を確認します。


ブラウザにSubscription confirmedというメッセージが表示されます。


サブスクリプションが確認されると、状態PendingからActiveに変わります。

以上で通知サービスのトピックとサブスクリプションの作成が完了しました。メッセージの送信にトピックのOCIDを使用するため、OCIDのコピーを取得しておきます。



メッセージを送信するユーザーの作成



トピックへメッセージを送信する権限を持ったユーザーを作成します。

OCIコンソールよりアイデンティティとセキュリティに含まれるユーザーを開きます。

ユーザーの作成を実行します。


ユーザー・タイプの選択としてIAMユーザーを選びます。作成するユーザーの名前notification-botとし、説明通知を行うと入力します。

作成を実行します。


ユーザーnotification-botが作成されたら、リソースよりAPIキーを開きます。

APIキーの追加を実行します。


APIキーの追加を行うダイアログが開きます。APIキー・ペアの生成を選択し、秘密キーのダウンロードを実行します。ダウンロードされた秘密キーが含まれるファイル名は、忘れないようにしてください。

その後、追加をクリックします。


追加をクリックすると構成ファイルがプレビューされます。この情報を使ってデータベースにクリデンシャルを作成します。コピーをして、後で参照できるように保存しておきます。

情報を保存したら、閉じるをクリックします。


必ずしも必要な作業ではありませんが、ユーザー機能の編集をしておきます。


ユーザー機能のAPIキーだけチェックを残し、他のチェックをすべて外します。

変更の保存を実行します。


続いて通知を実行する権限を与えるグループを作成します。

アイデンティティグループを開き、グループの作成を実行します。


画面右にドロワーが開きます。

作成するグループの名前notif-bot-group説明通知する権限を持つグループと記述します。

作成を実行します。


グループnotif-bot-groupが作成されます。

リソースグループ・メンバーより、ユーザーをグループに追加を実行し、先ほど作成したユーザーnotificatiuon-botをグループに追加します。


ダイアログが開くので、ユーザーとしてnotification-botを選択し、追加をクリックします。


以上で、グループnotif-bot-groupに、ユーザーnotification-botが追加されました。

グループの準備は以上で完了です。


最後にポリシーを定義します。

アイデンティティポリシーを開きます。ポリシーの作成を実行します。


作成するポリシーの名前AllowNotificationPolicyとします。説明通知の許可と記述します。コンパートメントとしてルートを選択し、ポリシー・ビルダーでは手動エディタの表示ONにします。ポリシー・ステートメントとして以下を記述します。グループnotif-bot-groupにテナンシに含まれる通知のトピックの使用を許可しています。

allow group notif-bot-group to use ons-topic in tenancy

以上を設定を行い、作成をクリックします。


ポリシーAllowNotificationPolicyが作成されました。


以上で、トピックへメッセージを送信する権限を持ったユーザーnotification-botの作成が完了しました。


APEXアプリケーションを作成する前準備



APEXアプリケーションでは、通知に関するPL/SQL SDKが実装されているパッケージDBMS_CLOUD_OCI_ONS_NOTIFICATION_DATA_PLANEを使用します。関係するタイプとパッケージDBMS_CLOUDを含めて、APEXのワークスペース・スキーマで使えるように、実行権限を与えます。

データベース・アクションSQLより、以下のコマンドを実行します。
grant execute on dbms_cloud_oci_ons_notification_data_plane_publish_message_response_t to apexdev;
grant execute on dbms_cloud_oci_ons_message_details_t to apexdev;
grant execute on DBMS_CLOUD_OCI_ONS_NOTIFICATION_DATA_PLANE to apexdev;
grant execute on dbms_cloud to apexdev;


APIの呼び出しに使用するクリデンシャルを作成します。

APEXのSQLワークショップSQLコマンドを開きます。

DBMS_CLOUD.CREATE_CREDENTIALを実行します。クリデンシャル名MY_NOTIF_CREDとします。
declare
     C_RSA_KEY constant varchar2(4000) := q'~
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC4CJLnF7vcPADr
s/loy/A/sT6H+j2pZNAQkBU48WpMeRgHqkZ7TNyCzn1+q3Vj+drO9lPT1SNVbsb9
ダウンロードした秘密キーのファイルの内容
4+6RJWJS0i7Oai6ZMfxnCV3vzzbXxs1hluaD2p3u6JQosDUzQ/qatt+PVWVldoJz
HPWM0pRKD8zT3IsL41+VEweN
-----END PRIVATE KEY-----
~';
    l_oneline_key varchar2(4000);
begin
    --  一行にする。
    l_oneline_key := regexp_replace(
        C_RSA_KEY
        ,'(-+((BEGIN|END) (RSA )?(PUBLIC|PRIVATE) KEY)-+\s?|\s)'
        , '');
    dbms_cloud.create_credential(
        credential_name => 'MY_NOTIF_CRED'
        , user_ocid => '構成ファイルのuser=で指定されているOCID'
        , tenancy_ocid => '構成ファイルのtenancy=で指定されているOCID'
        , private_key => l_oneline_key
        , fingerprint => '構成ファイルのfingerprint=で指定されている値'
    );
end;
/
引数のuser_ocid、tenancy_ocid、fingerprintはAPIキーを登録したときに表示された、構成ファイルに記載があります。秘密キーのデータは内容を一行にして、private_keyに与えます。


作成したクリデンシャルは、ビューUSER_CREDENTIALSより確認できます。

select credential_name, enabled from user_credentials



APEXアプリケーションの作成



通知を送信するAPEXアプリケーションを作成します。

アプリケーション作成ウィザードを起動し、空のアプリケーションを作成します。名前通知のテストとします。

アプリケーションの作成を実行します。


アプリケーションが作成されたら、ホーム・ページをページ・デザイナで開きます。


通知に使用するページ・アイテムやボタンを配置するリージョンを作成します。

Bodyリージョンを作成し、識別タイトル通知タイプ静的コンテンツとします。


通知を送信するファンクションDBMS_CLOUD_OCI_ONS_NOTIFICATION_DATA_PLANE.PUBLISH_MESSAGEの引数となるページ・アイテムを作成します。

P1_REGIONにリージョン、P1_TOPICに宛先となるトピックのOCID、P1_TITLEに通知のタイトル、P1_BODYに通知の本文を設定します。それに加えて送信ボタンを作成します。

ページ・アイテムP1_REGION識別タイプテキスト・フィールドラベルリージョンとします。


ページ・アイテムP1_TOPIC識別タイプテキスト・フィールドラベルトピックとします。


ページ・アイテムP1_TITLE識別タイプテキスト・フィールドラベルタイトルとします。


ページ・アイテムP1_BODY識別タイプテキスト領域ラベル本文とします。


最後にボタンを作成します。

作成したボタンの識別ボタン名B_SUBMITラベル送信とします。


画面上へのコンポーネントの配置は以上です。

続いて、ボタン送信を押したときに実行するプロセスを作成します。左ペインでプロセス・ビューを開き、プロセスを作成します。

作成したプロセスの識別名前通知の送信とします。タイプとしてコードの実行を選択します。ソースPL/SQLコードとして、以下を記述します。

サーバー側の条件ボタン押下時として、B_SUBMITを選択します。


以上で、OCIの通知にメッセージを送信するAPEXアプリケーションは完成です。

アプリケーションを実行すると、記事の先頭のGIF動画のように動作します。

Slackに通知するだけであれば、APEXから直接Slackを呼び出した方がメッセージのフォーマットもできますし、Incoming Webhookではなく、chat.postMessageによるインテグレーションも可能です。そのため、APEXからOCIの通知経由でSlackにメッセージを送信するケースはあまりないと思います。どちらかというと、APEXアプリケーションをOCIの監視フレームワークに組み込む際に活用できる気がします。

今回作成したアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/oci-notification-app.sql

Oracle APEXのアプリケーション作成の参考になれば幸いです。