はじめに
自己学習を兼ねて、Amazon S3にファルがアップロードされたら、それをトリガーにしてLambdaファンクションが起動し、LambdaファンクションがAutonomous Databaseに接続してアップロードされたファイルをAmazon S3からOCI Object Storageに移動するPL/SQLプロシージャを実行するという仕組みを構築してみました。
処理の流れのイメージは以下のようになります。
-
Amazon S3のバケットにファイルをアップロード
-
Amazon S3バケットのオブジェクト作成イベントをLambdaに通知
-
LambdaからAutonomous Databaseにアクセス
-
Amazon S3にアップロードされたファイルをOCI Object Storageに移動するPL/SQLプロシージャをLambdaから実行
-
PL/SQLプロシージャによって、Amazon S3にアップロードされたファイルがOCI Object Storageに移動される
※なお、Python、Lambdaに関して初心者ですので、最低限動くといったコーディング、設定しか行っていません。実装にあたっては、エラーハンドリング等を追加し充分に検証を行ってから実装してください。こちらの内容を元に実装されたことによる問題について、当方は一切の責任を負いません。
また、こちらの内容に関するOracle Supportへのご質問等はご遠慮ください。
1. 事前準備
・OCI Object StorageとAmazon S3に同じ名前のバケットを作成します。
(今回はobject-move-test-bucketという名前のバケットを作成しました。)
・Autonomous Databasのリソース・プリンシパルを有効化し、OCI Object Storageへのアクセスを許可します。
リソース・プリンシパルの使用方法については、こちらを参照ください。
・Autonomous DatabaseからAmazon S3にアクセスするためのクレデンシャルの作成します。
今回はAWS_S3_CREDという名前のARNを使用したロールベースのクレデンシャルを作成し、使用しました。
ARNを使用したロール・ベースのクレデンシャルの作成については、こちらを参照ください。
・AWS CLI、SAM CLIが利用可能な環境を準備します。
2. PL/SQLプロシージャの作成
バケット名とオブジェクト名を引数として渡すと、AWS S3からOCI Object Storageにオブジェクトを移動するPL/SQLプロシージャmove_awss3_to_ociosを作成します。
Autonomous Databaseには、2つのバケット間でオブジェクトを移動するPL/SQLプロシージャDBMS_CLOUD.MOVE_OBJECTが用意されていますので、このプロシージャを使用します。
CREATE OR REPLACE PROCEDURE move_awss3_to_ocios ( bucket_name IN VARCHAR2, object_name IN VARCHAR2)
IS
source_uri VARCHAR2(200);
target_uri VARCHAR2(200);
BEGIN
source_uri := 'https://'||bucket_name||'.s3.ap-northeast-1.amazonaws.com/'||object_name;
target_uri := 'https://objectstorage.ap-tokyo-1.oraclecloud.com/n/namespace/b/'||bucket_name||'/o/'||object_name;
DBMS_CLOUD.MOVE_OBJECT (
source_credential_name => 'AWS_S3_CRED',
source_object_uri => source_uri,
target_credential_name => 'OCI$RESOURCE_PRINCIPAL',
target_object_uri => target_uri
);
END;
/
adminユーザとして、SQL*PlusからAutonomous Databaseに接続します。
[oracle@oracle23ai ~]$ sqlplus admin/Demo#1Demo#1@adw23ai
SQL*Plus: Release 23.0.0.0.0 - Production on Fri Jul 26 11:44:46 2024
Version 23.4.0.24.05
Copyright (c) 1982, 2024, Oracle. All rights reserved.
Last Successful login time: Fri Jul 26 2024 11:42:17 +09:00
Connected to:
Oracle Database 23ai Enterprise Edition Release 23.0.0.0.0 - Production
Version 23.5.0.24.06
SQL>
上記のDDLを実行して、PL/SQLプロシージャmove_awss3_to_ociosを作成します。
の部分は、テナントのObject Storageのネームスペースを入力します。
SQL> CREATE OR REPLACE PROCEDURE move_awss3_to_ocios ( bucket_name IN VARCHAR2, object_name IN VARCHAR2)
2 IS
3 source_uri VARCHAR2(200);
4 target_uri VARCHAR2(200);
5
6 BEGIN
7 source_uri := 'https://'||bucket_name||'.s3.ap-northeast-1.amazonaws.com/'||object_name;
8 target_uri := 'https://objectstorage.ap-tokyo-1.oraclecloud.com/n/<namespace>/b/'||bucket_name||'/o/'||object_name;
9
10 DBMS_CLOUD.MOVE_OBJECT (
11 source_credential_name => 'AWS_S3_CRED',
12 source_object_uri => source_uri,
13 target_credential_name => 'OCI$RESOURCE_PRINCIPAL',
14 target_object_uri => target_uri
15 );
16 END;
17 /
Procedure created.
SQL>
PL/SQLプロシージャmove_awss3_to_ociosが作成できました。
3. Lambdaファンクションの作成
sam initを実行して新規アプリケーションを初期化します。
今回はAWS Quick Start Templatesに用意されているHello World Exampleをテンプレートとして使用しました。
プロジェクト名はmoveobjectとしました。
(mypy) myuser@mymac sam % sam init
You can preselect a particular runtime or package type when using the `sam init` experience.
Call `sam init --help` to learn more.
Which template source would you like to use?
1 - AWS Quick Start Templates
2 - Custom Template Location
Choice: 1
Choose an AWS Quick Start application template
1 - Hello World Example
2 - Data processing
3 - Hello World Example with Powertools for AWS Lambda
4 - Multi-step workflow
5 - Scheduled task
6 - Standalone function
7 - Serverless API
8 - Infrastructure event management
9 - Lambda Response Streaming
10 - Serverless Connector Hello World Example
11 - Multi-step workflow with Connectors
12 - GraphQLApi Hello World Example
13 - Full Stack
14 - Lambda EFS example
15 - DynamoDB Example
16 - Machine Learning
Template: 1
Use the most popular runtime and package type? (Python and zip) [y/N]: y
Would you like to enable X-Ray tracing on the function(s) in your application? [y/N]:
Would you like to enable monitoring using CloudWatch Application Insights?
For more info, please view https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/cloudwatch-application-insights.html [y/N]:
Would you like to set Structured Logging in JSON format on your Lambda functions? [y/N]:
Project name [sam-app]: moveobject
-----------------------
Generating application:
-----------------------
Name: moveobject
Runtime: python3.9
Architectures: x86_64
Dependency Manager: pip
Application Template: hello-world
Output Directory: .
Configuration file: moveobject/samconfig.toml
Next steps can be found in the README file at moveobject/README.md
Commands you can use next
=========================
[*] Create pipeline: cd moveobject && sam pipeline init --bootstrap
[*] Validate SAM template: cd moveobject && sam validate
[*] Test Function in the Cloud: cd moveobject && sam sync --stack-name {stack-name} --watch
(mypy) myuser@mymac sam %
作成されたmoveobjectディレクトリに移動します。
(mypy) myuser@mymac sam % cd moveobject
(mypy) myuser@mymac moveobject % ls
README.md events samconfig.toml tests
__init__.py hello_world template.yaml
(mypy) myuser@mymac moveobject %
hello_worldディレクトリに移動します。
(mypy) myuser@mymac moveobject % cd hello_world
(mypy) myuser@mymac hello_world % ls
__init__.py app.py requirements.txt
(mypy) kmyuser@mymac hello_world %
今回はAutonomous Databaseへのアクセスにpython-oracledbを使用するので、reqirements.txtにoracledbを追加します。
(mypy) myuser@mymac hello_world % vi requirements.txt
requests
oracledbを追加して保存します。
requests
oracledb
pip installで必要なパッケージをインストールします。
(mypy) myuser@mymac hello_world % pip install -r requirements.txt
アプリケーション本体のapp.pyを編集します。
(mypy) myuser@mymac hello_world % vi app.py
以下のような内容に書き換えます。
import json
import oracledb
import os
# 環境変数を取得
un = os.environ.get('PYTHON_USERNAME')
pw = os.environ.get('PYTHON_PASSWORD')
cs = os.environ.get('PYTHON_CONNECTSTRING')
def lambda_handler(event, context):
# イベント通知からバケット名とオブジェクト名を取得
bucket_name = event['Records'][0]['s3']['bucket']['name']
object_name = event['Records'][0]['s3']['object']['key']
# Autonomous Databaseに接続し、バケット名、オブジェクト名を引数としてmove_awss3_to_ociosプロシージャを実行
with oracledb.connect(user=un, password=pw, dsn=cs) as connection:
with connection.cursor() as cursor:
cursor.callproc('move_awss3_to_ocios', [bucket_name, object_name])
return {
"statusCode": 200,
"body": json.dumps({
"message": "hello world",
# "location": ip.text.replace("\n", "")
}),
}
moveobjectディレクトリに移動します。
(mypy) myuser@mymac hello_world % cd ..
(mypy) myuser@mymac moveobject % ls
README.md events samconfig.toml tests
__init__.py hello_world template.yaml
(mypy) myuser@mymac moveobject %
sam buildでアプリケーションをビルドを実行します。
(mypy) myuser@mymac moveobject % sam build
Starting Build use cache
Manifest file is changed (new hash: 2768310a16637613860e1081461caa9f) or
dependency folder (.aws-sam/deps/842f4bbf-8ed0-453f-8945-1a0ca9c9f08e) is
missing for (HelloWorldFunction), downloading dependencies and copying/building
source
Building codeuri: /Users/kyamakaw/sam/moveobject/hello_world runtime: python3.9
metadata: {} architecture: x86_64 functions: HelloWorldFunction
Running PythonPipBuilder:CleanUp
Running PythonPipBuilder:ResolveDependencies
Running PythonPipBuilder:CopySource
Running PythonPipBuilder:CopySource
Build Succeeded
Built Artifacts : .aws-sam/build
Built Template : .aws-sam/build/template.yaml
Commands you can use next
=========================
[*] Validate SAM template: sam validate
[*] Invoke Function: sam local invoke
[*] Test Function in the Cloud: sam sync --stack-name {{stack-name}} --watch
[*] Deploy: sam deploy --guided
(mypy) myuser@mymac moveobject %
sam deployでアプリケーションをLambdaにファンクションとしてデプロイします。
(mypy) myuser@mymac moveobject % sam deploy --stack-name moveobject --guided
Configuring SAM deploy
======================
Looking for config file [samconfig.toml] : Found
Reading default arguments : Success
Setting default arguments for 'sam deploy'
=========================================
Stack Name [moveobject]:
AWS Region [ap-northeast-1]:
#Shows you resources changes to be deployed and require a 'Y' to initiate deploy
Confirm changes before deploy [Y/n]:
#SAM needs permission to be able to create roles to connect to the resources in your template
Allow SAM CLI IAM role creation [Y/n]:
#Preserves the state of previously provisioned resources when an operation fails
Disable rollback [y/N]:
HelloWorldFunction has no authentication. Is this okay? [y/N]: y
Save arguments to configuration file [Y/n]:
SAM configuration file [samconfig.toml]:
SAM configuration environment [default]:
Looking for resources needed for deployment:
Managed S3 bucket: aws-sam-cli-managed-default-samclisourcebucket-e7cuyvsbwyhw
A different default S3 bucket can be set in samconfig.toml and auto resolution of buckets turned off by setting resolve_s3=False
Parameter "stack_name=moveobject" in [default.deploy.parameters] is
defined as a global parameter [default.global.parameters].
This parameter will be only saved under [default.global.parameters] in
/Users/kyamakaw/sam/moveobject/samconfig.toml.
Saved arguments to config file
Running 'sam deploy' for future deployments will use the parameters saved above.
The above parameters can be changed by modifying samconfig.toml
Learn more about samconfig.toml syntax at
https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-config.html
Uploading to moveobject/c52a52a03cc30a46b36c64693968e2ce 262144 / 7426200 (3.5Uploading to moveobject/c52a52a03cc30a46b36c64693968e2ce 524288 / 7426200 (7.0Uploading to moveobject/c52a52a03cc30a46b36c64693968e2ce 786432 / 7426200 (10.Uploading to moveobject/c52a52a03cc30a46b36c64693968e2ce 1048576 / 7426200 (14Uploading to moveobject/c52a52a03cc30a46b36c64693968e2ce 1310720 / 7426200 (17Uploading to moveobject/c52a52a03cc30a46b36c64693968e2ce 1572864 / 7426200 (21Uploading to moveobject/c52a52a03cc30a46b36c64693968e2ce 1835008 / 7426200 (24Uploading to moveobject/c52a52a03cc30a46b36c64693968e2ce 2097152 / 7426200 (28Uploading to moveobject/c52a52a03cc30a46b36c64693968e2ce 2359296 / 7426200 (31Uploading to moveobject/c52a52a03cc30a46b36c64693968e2ce 2621440 / 7426200 (35Uploading to moveobject/c52a52a03cc30a46b36c64693968e2ce 2883584 / 7426200 (38Uploading to moveobject/c52a52a03cc30a46b36c64693968e2ce 3145728 / 7426200 (42Uploading to moveobject/c52a52a03cc30a46b36c64693968e2ce 3407872 / 7426200 (45Uploading to moveobject/c52a52a03cc30a46b36c64693968e2ce 3670016 / 7426200 (49Uploading to moveobject/c52a52a03cc30a46b36c64693968e2ce 3932160 / 7426200 (52Uploading to moveobject/c52a52a03cc30a46b36c64693968e2ce 4194304 / 7426200 (56Uploading to moveobject/c52a52a03cc30a46b36c64693968e2ce 4456448 / 7426200 (60Uploading to moveobject/c52a52a03cc30a46b36c64693968e2ce 4718592 / 7426200 (63Uploading to moveobject/c52a52a03cc30a46b36c64693968e2ce 4980736 / 7426200 (67Uploading to moveobject/c52a52a03cc30a46b36c64693968e2ce 5242880 / 7426200 (70Uploading to moveobject/c52a52a03cc30a46b36c64693968e2ce 5505024 / 7426200 (74Uploading to moveobject/c52a52a03cc30a46b36c64693968e2ce 5767168 / 7426200 (77Uploading to moveobject/c52a52a03cc30a46b36c64693968e2ce 6029312 / 7426200 (81Uploading to moveobject/c52a52a03cc30a46b36c64693968e2ce 6291456 / 7426200 (84Uploading to moveobject/c52a52a03cc30a46b36c64693968e2ce 6553600 / 7426200 (88Uploading to moveobject/c52a52a03cc30a46b36c64693968e2ce 6815744 / 7426200 (91Uploading to moveobject/c52a52a03cc30a46b36c64693968e2ce 7077888 / 7426200 (95Uploading to moveobject/c52a52a03cc30a46b36c64693968e2ce 7340032 / 7426200 (98Uploading to moveobject/c52a52a03cc30a46b36c64693968e2ce 7426200 / 7426200 (100.00%)
Deploying with following values
===============================
Stack name : moveobject
Region : ap-northeast-1
Confirm changeset : True
Disable rollback : False
Deployment s3 bucket : aws-sam-cli-managed-default-samclisourcebucket-e7cuyvsbwyhw
Capabilities : ["CAPABILITY_IAM"]
Parameter overrides : {}
Signing Profiles : {}
Initiating deployment
=====================
Uploading to moveobject/03f3a4731daa7d55e4fe6bb863b9ba65.template 1208 / 1208 (100.00%)
Waiting for changeset to be created..
CloudFormation stack changeset
-------------------------------------------------------------------------------------------------
Operation LogicalResourceId ResourceType Replacement
-------------------------------------------------------------------------------------------------
+ Add HelloWorldFunctionHell AWS::Lambda::Permissio N/A
oWorldPermissionProd n
+ Add HelloWorldFunctionRole AWS::IAM::Role N/A
+ Add HelloWorldFunction AWS::Lambda::Function N/A
+ Add ServerlessRestApiDeplo AWS::ApiGateway::Deplo N/A
yment47fc2d5f9d yment
+ Add ServerlessRestApiProdS AWS::ApiGateway::Stage N/A
tage
+ Add ServerlessRestApi AWS::ApiGateway::RestA N/A
pi
-------------------------------------------------------------------------------------------------
Changeset created successfully. arn:aws:cloudformation:ap-northeast-1:************:changeSet/samcli-deploy1721954219/14beaea2-0e05-4400-9136-3d975a321b85
Previewing CloudFormation changeset before deployment
======================================================
Deploy this changeset? [y/N]: y
2024-07-26 09:37:14 - Waiting for stack create/update to complete
CloudFormation events from stack operations (refresh every 5.0 seconds)
-------------------------------------------------------------------------------------------------
ResourceStatus ResourceType LogicalResourceId ResourceStatusReason
-------------------------------------------------------------------------------------------------
CREATE_IN_PROGRESS AWS::CloudFormation::S moveobject User Initiated
tack
CREATE_IN_PROGRESS AWS::IAM::Role HelloWorldFunctionRole -
CREATE_IN_PROGRESS AWS::IAM::Role HelloWorldFunctionRole Resource creation
Initiated
CREATE_COMPLETE AWS::IAM::Role HelloWorldFunctionRole -
CREATE_IN_PROGRESS AWS::Lambda::Function HelloWorldFunction -
CREATE_IN_PROGRESS AWS::Lambda::Function HelloWorldFunction Resource creation
Initiated
CREATE_IN_PROGRESS AWS::Lambda::Function HelloWorldFunction Eventual consistency
check initiated
CREATE_IN_PROGRESS AWS::ApiGateway::RestA ServerlessRestApi -
pi
CREATE_IN_PROGRESS AWS::ApiGateway::RestA ServerlessRestApi Resource creation
pi Initiated
CREATE_COMPLETE AWS::ApiGateway::RestA ServerlessRestApi -
pi
CREATE_IN_PROGRESS AWS::ApiGateway::Deplo ServerlessRestApiDeplo -
yment yment47fc2d5f9d
CREATE_IN_PROGRESS AWS::Lambda::Permissio HelloWorldFunctionHell -
n oWorldPermissionProd
CREATE_IN_PROGRESS AWS::Lambda::Permissio HelloWorldFunctionHell Resource creation
n oWorldPermissionProd Initiated
CREATE_IN_PROGRESS AWS::ApiGateway::Deplo ServerlessRestApiDeplo Resource creation
yment yment47fc2d5f9d Initiated
CREATE_COMPLETE AWS::Lambda::Function HelloWorldFunction -
CREATE_COMPLETE AWS::Lambda::Permissio HelloWorldFunctionHell -
n oWorldPermissionProd
CREATE_COMPLETE AWS::ApiGateway::Deplo ServerlessRestApiDeplo -
yment yment47fc2d5f9d
CREATE_IN_PROGRESS AWS::ApiGateway::Stage ServerlessRestApiProdS -
tage
CREATE_IN_PROGRESS AWS::ApiGateway::Stage ServerlessRestApiProdS Resource creation
tage Initiated
CREATE_COMPLETE AWS::ApiGateway::Stage ServerlessRestApiProdS -
tage
CREATE_COMPLETE AWS::CloudFormation::S moveobject -
tack
-------------------------------------------------------------------------------------------------
CloudFormation outputs from deployed stack
-------------------------------------------------------------------------------------------------
Outputs
-------------------------------------------------------------------------------------------------
Key HelloWorldFunctionIamRole
Description Implicit IAM Role created for Hello World function
Value arn:aws:iam::************:role/moveobject-
HelloWorldFunctionRole-2vpYoNBI2ZkL
Key HelloWorldApi
Description API Gateway endpoint URL for Prod stage for Hello World function
Value https://v1o97s67gf.execute-api.ap-northeast-1.amazonaws.com/Prod/hello/
Key HelloWorldFunction
Description Hello World Lambda Function ARN
Value arn:aws:lambda:ap-northeast-1:************:function:moveobject-
HelloWorldFunction-Fh6UhaLBn4LT
-------------------------------------------------------------------------------------------------
Successfully created/updated stack - moveobject in ap-northeast-1
(mypy) myuser@mymac moveobject %
4. Lambdaファンクションの設定
S3バケットにオブジェクトが作成された時にLambdaファンクションが起動するように、ファンクションにトリガーを追加します。
AWSコンソールから、作成したLambdaファンクションの詳細画面にアクセスし、設定タブにアクセスします。
バケット名に1.で作成したバケットを選択します。
イベントタイプはデフォルトで「全てのオブジェクト作成イベント」が設定されているので、そのままにします。
入力が完了したら、「追加」をクリックして、トリガを追加します。
トリガーが追加されました。
Lambdaファンクションの環境変数を設定します。
今回は、Autonomous Databaseに接続する際のユーザ名、パスワード、接続文字列を環境変数に設定し、Lambdaファンクションから参照します。
PYTHON_USERNAME:ユーザ名
PYTHON_PASSWORD:パスワード
PYTHON_CONNECTSTRING:接続文字列
左側のメニューから「環境変数」をクリックし、「編集」をクリックします。
「環境変数の追加」をクリックして入力欄を追加し、PYTHON_USERNAME、PYTHON_PASSWORD、PYTHON_CONNECTSTRINGの値をそれぞれ設定して「保存」をクリックします。
5. 動作確認
この時点では、OCI Object Storageバケット、Amazon S3バケットにファイル(オブジェクト)はありません。
S3バケットにファイルempdata1.csvをアップロードします。
Object Storageのオブジェクトの表示をリフレッシュします。
S3バケットにアップロードしたファイルが同じ名前のObject Storageバケットに移動されていることが確認できました。
まとめ
Amazon S3へのファイルのアップロードをトリガーとしてAutonomous Database内のPL/SQLプロシージャを実行し、ファイルの移動処理を行うことができることを確認できました。
参考文献
・リソース・プリンシパルを使用したOracle Cloud Infrastructureリソースへのアクセス
・Amazonリソース名(ARN)を使用したAWSリソースへのアクセス
・AWS CLIの最新バージョンのインストールまたは更新
・AWS SAM CLI のインストール
・sam init コマンドを使用してアプリケーションを作成する
・sam build
・sam deploy
・The python-oracledb driver for Oracle Database
・DBMS_CLOUD.MOVE_OBJECTプロシージャ