0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【OCI】FunctionsでObject Storage上のCSVをAutonomous Databaseに取り込む(Functions編)

0
Last updated at Posted at 2026-02-09

はじめに

本記事はOCIのEventsを起点としたCSV自動取込構成を段階的に解説する連載の第2回です。

第1回ではObject StorageへのファイルアップロードをEventsで検知し、Notificationsで通知する最小構成を紹介しました。
以下の記事で、その内容を解説しています。

今回はOCI Functions単体にフォーカスし、Object Storage上のCSVファイルを読み込み、Autonomous Databaseにデータを登録する処理を実装します。

本記事ではEvents連携は行いません。
Functionsを「単体で正しく動かす」ことを目的とします。


前提条件・補足事項

本記事では以下がすでに準備されている前提で進めます。

  • OCIアカウントを作成済み
  • Object Storage / Functions / OCIRを操作できる権限があること
  • OCI Functions環境 / アプリケーション作成済み
  • Autonomous Database(ADB)作成 / Walletダウンロード済み
  • Object Storageバケット作成済み
  • 認証トークン作成済み(OCIRログイン用、Functionsイメージpush目的)
  • Docker Hub(docker.io)アカウント作成済み、認証トークン作成済み
    (OCI Functionsの実行環境となるベースイメージを取得するため)

構成イメージ

image.png


目次

  1. 構成概要
  2. 事前準備
  3. Functionsの実装
  4. fn invokeによる動作確認

1. 構成概要

今回の構成は以下の通りです。

(CSVをObject Storageへ手動アップロード)
        ↓
[fn invoke(Cloud Shellから起動)]
        ↓
[OCI Functions(Python)]
        ↓
[Object Storage]
        ↓
[Autonomous Database]

予めObject Storage上のCSVファイルを手動でアップロードしておき、
OCI Functionsを起動すると、Object StorageからCSVファイルを取得し、
その内容をAutonomous DatabaseにINSERTします。


2. 事前準備

本章ではOCI Functionsで処理するための事前準備として、
Autonomous Databaseのテーブル作成と、Object Storageへ配置するCSVファイルを用意します。


2.1 Autonomous Databaseのテーブル作成

Autonomous Databaseに接続し、CSV取込用のテーブルを作成します。
本記事では以下のシンプルなテーブルを使用します。

CREATE TABLE T_EVENTS (
  ID   NUMBER,
  NAME VARCHAR2(100)
);

※ユーザーはADMINを想定しています。
※制約やインデックスは本記事では設定しません。


2.2 CSVファイルの作成

次にObject StorageへアップロードするCSVファイルを作成します。

以下の内容でCSVファイルを作成してください。

id,name
1,data01
2,data02
3,data03

ファイル名は例として t_events.csv とします。

作成したCSVファイルを、事前に作成済みのObject Storageバケットへ
手動でアップロードしておきます。

以上で事前準備は完了です。
次章ではOCI Functionsの実装を行います。


3. Functionsの実装

本章ではOCI Functionsを作成します。
Object Storage上のCSVをAutonomous Databaseに登録する処理を実装します。


3.1 OCIRリポジトリの作成

Functionsをデプロイすると、コンテナイメージは
OCI Container Registry(OCIR)にpushされます。

そのためFunctions用のOCIRリポジトリを事前に作成します。

本記事では作業ディレクトリ名と揃えるため、
以下の名前でリポジトリを作成します。

  • リポジトリ名:csv_to_adb

OCI Consoleの
メニュー → 開発者サービス → コンテナ・レジストリ → リポジトリ
から、「リポジトリの作成」を選択します。

表示された画面で、リポジトリ名に csv_to_adb を指定して作成してください。

image.png


3.2 Cloud Shellについて

本記事では作業環境としてCloud Shellを使用します。

OCI Console右上のCloud Shellアイコンから起動できます。

image.png

Cloud Shellには以下のツールがあらかじめインストールされています。

  • docker
  • fn CLI
  • OCI CLI

ローカル環境の構築は行いません。
Cloud Shell上で作業を進めます。


3.3 ログイン(Docker Hub / OCIR)

Functionsのビルドとデプロイに必要なため、
Docker HubとOCIRへログインします。


3.3.1 Docker Hub(ベースイメージ取得用)

OCI Functionsのビルド時に使用するベースイメージは、
Docker Hubから取得されます。

そのため、事前にDocker Hubへログインしておきます。

docker login docker.io

ユーザー名にはDocker Hubのユーザー名を指定します。
パスワードには Docker Hubで作成した認証トークン を入力してください。

ログインし直す場合は以下を実行します。

docker logout docker.io

3.3.2 OCIR(イメージpush用)

Functionsのデプロイ時に作成されるコンテナイメージは、
OCI Container Registry(OCIR)にpushされます。

以下のコマンドでOCIRへログインします。

docker login nrt.ocir.io -u '<テナント名>/<ユーザー名>'

パスワードには OCIで作成した認証トークン を入力してください。

続いて、fn CLIのcontextを設定します。

fn update context oracle.compartment-id <コンパートメントOCID>
fn update context registry nrt.ocir.io/<テナント名>

<コンパートメントOCID>
Functionsアプリケーションを作成したコンパートメントのOCIDを指定します。
OCI Consoleの
「アイデンティティとセキュリティ → コンパートメント」
から確認できます。

<テナント名>
OCIテナンシー名を指定します。


3.4 作業ディレクトリ作成とWallet展開

Functions用の作業ディレクトリを作成します。
本記事では csv_to_adb を使用します。

cd ~
mkdir -p ~/csv_to_adb/wallet

3.4.1 Walletの展開

事前にダウンロードしたWalletのzipファイルを、Cloud Shellのホームディレクトリ(~)に配置します。

Wallet名が Wallet_db01.zip の場合は以下を実行します。

unzip -o ~/Wallet_db01.zip -d ~/csv_to_adb/wallet

最低限、以下のファイルが存在することを確認します。

ls -la ~/csv_to_adb/wallet | egrep -n 'tnsnames\.ora|sqlnet\.ora|cwallet\.sso|ewallet\.p12|ewallet\.pem'

最終的な作業ディレクトリの構成は以下のようになります。

~/csv_to_adb/
├── func.yaml
├── func.py
├── requirements.txt
└── wallet/
    ├── README
    ├── cwallet.sso
    ├── ewallet.p12
    ├── ewallet.pem
    ├── keystore.jks
    ├── ojdbc.properties
    ├── sqlnet.ora
    ├── tnsnames.ora
    └── truststore.jks

※ Wallet内のファイル構成は、ADB作成時の設定により多少異なる場合があります。


3.4.2 Functions用 sqlnet.oraの設定

Functions実行時はWalletの配置先が /function/wallet 固定となります。
sqlnet.ora を以下の内容に変更します。

cat > ~/csv_to_adb/wallet/sqlnet.ora <<'EOF'
WALLET_LOCATION =
  (SOURCE =
    (METHOD = file)
    (METHOD_DATA =
      (DIRECTORY = /function/wallet)
    )
  )

SSL_SERVER_DN_MATCH = yes
DISABLE_OOB = ON
EOF

3.5 Functionsソース作成

Functionsで必要なファイルをcsv_to_adbの中に作成していきます。


3.5.1 func.py

以下の内容で func.py を作成します。
必ずJSONでレスポンスを返す構成とします。

※ パスワードについて
以下の値は 自分の環境に合わせて書き換えてください

  • ADB_PASSWORD
    Autonomous Databaseの ADMINユーザーのパスワード を指定します。
    ADB作成時に設定したパスワードです。

  • WALLET_PASSWORD
    Autonomous DatabaseのWalletを ダウンロードする際に設定したパスワード を指定します。
    Walletファイル(ewallet.p12 など)を利用するために必要です。

※本記事は検証目的のため、パスワードをソースコード内に直接記載しています。
実運用ではOCI Vaultや環境変数の利用を検討してください。

cat > ~/csv_to_adb/func.py <<'EOF'
import csv
import io
import json
import traceback
from fdk import response

ADB_USER = "ADMIN"
ADB_PASSWORD = "<ADB_ADMIN_PASSWORD>"
ADB_DSN = "db01_low"

WALLET_PASSWORD = "<WALLET_PASSWORD>"
WALLET_DIR = "/function/wallet"

def handler(ctx, data: io.BytesIO = None):
    try:
        body = json.loads((data.getvalue() or b"{}").decode("utf-8"))

        if "data" in body and "resourceName" in body["data"]:
            namespace = body["data"]["additionalDetails"]["namespace"]
            bucket = body["data"]["additionalDetails"]["bucketName"]
            object_name = body["data"]["resourceName"]
            trigger = "events"
        else:
            namespace = body["namespace"]
            bucket = body["bucket"]
            object_name = body["object"]
            trigger = "manual"

        if not object_name.lower().endswith(".csv"):
            return response.Response(
                ctx,
                status_code=200,
                response_data=json.dumps({
                    "ok": True,
                    "skipped": True,
                    "object": object_name
                }),
                headers={"Content-Type": "application/json"},
            )

        import oci
        import oracledb

        signer = oci.auth.signers.get_resource_principals_signer()
        os_client = oci.object_storage.ObjectStorageClient({}, signer=signer)

        obj = os_client.get_object(
            namespace_name=namespace,
            bucket_name=bucket,
            object_name=object_name
        )
        csv_text = obj.data.content.decode("utf-8", errors="replace")

        reader = csv.DictReader(io.StringIO(csv_text))
        rows = [(int(r["id"]), r["name"]) for r in reader]

        conn = oracledb.connect(
            user=ADB_USER,
            password=ADB_PASSWORD,
            dsn=ADB_DSN,
            config_dir=WALLET_DIR,
            wallet_location=WALLET_DIR,
            wallet_password=WALLET_PASSWORD,
            ssl_server_dn_match=True,
            disable_oob=True,
            tcp_connect_timeout=5.0,
        )

        with conn.cursor() as cur:
            cur.executemany(
                "INSERT INTO T_EVENTS (ID, NAME) VALUES (:1, :2)",
                rows
            )

        conn.commit()
        conn.close()

        return response.Response(
            ctx,
            status_code=200,
            response_data=json.dumps({
                "ok": True,
                "trigger": trigger,
                "inserted": len(rows)
            }),
            headers={"Content-Type": "application/json"},
        )

    except Exception as e:
        return response.Response(
            ctx,
            status_code=200,
            response_data=json.dumps({
                "ok": False,
                "error": str(e),
                "trace": traceback.format_exc()[-1500:]
            }),
            headers={"Content-Type": "application/json"},
        )
EOF

3.5.2 requirements.txt

cat > ~/csv_to_adb/requirements.txt <<'EOF'
fdk
oci
oracledb
EOF

3.5.3 func.yaml

cat > ~/csv_to_adb/func.yaml <<'EOF'
schema_version: 20180708
name: csv_to_adb
version: 0.0.1
runtime: python
entrypoint: /python/bin/fdk /function/func.py handler
EOF

3.6 デプロイ

Functionsをデプロイします。

--app には、事前に作成済みの OCI Functionsのアプリケーション名 を指定します。
本記事では func_test を使用しています。

cd ~/csv_to_adb
fn deploy --app func_test

※ビルド時に容量不足でエラーとなった場合は以下を実行します。

docker system prune -af --volumes
docker builder prune -af
fn deploy --app func_test

以上でFunctionsの実装は完了です。


4. fn invokeによる動作確認

本章では、作成したOCI Functionsを fn invoke で手動実行し、
CSVファイルがAutonomous Databaseに登録されることを確認します。


4.1 fn invokeでの実行

Cloud Shellで作業ディレクトリに移動し、以下のコマンドを実行します。

cd ~/csv_to_adb

echo -n '{
  "namespace":"[テナントのネームスペース]",
  "bucket":"[バケット名]",
  "object":"[インポート対象のCSVファイル名]"
}' | fn invoke func_test csv_to_adb
  • <Object Storageのネームスペース>
    Object Storageのネームスペースを指定します。

  • <バケット名>
    CSVファイルをアップロードしたObject Storageバケット名を指定します。

  • <アプリケーション名>
    OCI Functionsのアプリケーション名を指定します。
    本記事では func_test を使用しています。

  • <ファンクション名>
    Functionsのファンクション名を指定します。
    本記事では csv_to_adb を使用しています。


4.2 実行結果の確認

正常に実行されると、以下のようなJSONレスポンスが返ります。

{
  "ok": true,
  "trigger": "manual",
  "inserted": 3
}

inserted には、CSVファイルからINSERTされた行数が表示されます。


4.3 Autonomous Databaseの確認

Autonomous Databaseに接続し、データが登録されていることを確認します。

SELECT * FROM T_EVENTS ORDER BY ID;

CSVファイルの内容がテーブルに登録されていれば成功です。


4.4 APIGateway経由での呼び出し(参考)

本記事ではfn invokeによる手動実行で動作確認を行いましたが、
APIGateway経由でもFunctionsを呼び出すことができます。

APIGatewayを使うとHTTPでアクセスするだけで、
Functionsを起動できます。

過去にAPIGatewayを使ったFunctions呼び出しについては、
以下の記事で解説しています。

APIGatewayから呼び出す場合も、
リクエストボディにnamespace / bucket / objectを含めれば、
Functionsは同じように処理を実行します。

例えば以下のようなHTTP POSTリクエストを送信します。

curl -X POST <APIGatewayのURL> \
  -H "Content-Type: application/json" \
  -d '{"namespace":"[テナントのネームスペース]","bucket":"[バケット名]","object":"[インポート対象のCSVファイル名]"}'

以上で、fn invokeによる動作確認は完了です。


次回予告

次回は、Object Storageへのファイルアップロードを起点に、
OCI Eventsを使ってFunctionsを自動実行する構成を紹介します。

  • Object Storageイベントの設定
  • EventsからOCI Functionsを起動
  • CSVアップロードをトリガーにデータを自動登録

本記事で作成したFunctionsをそのまま利用し、
Events連携を追加するだけで構成が完成します。

▶ 続きはこちら(第3回)
※公開後にリンクを追加予定

0
1
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
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?