Paws::S3 で ECS タスクロールを用いてS3へファイルをアップロードする

この記事は [Perl Advent Calendar 2020](https://qiita.com/advent-calendar/2020/perl) の 12/6 の記事です
昨日は mp0liiu さんでした。

---

最近はあまり Perl を書いてないのですが少し触る機会があったので、
Paws::S3 で、ECS のタスクロールを用いて、Amazon S3 へファイルをアップロードする簡単な使い方を紹介をしようと思います。


# ECS のタスクロールについて
https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/task-iam-roles.html

Amazon ECS タスクには、ECS タスクの実行用の IAM ロールを使用することができます。
この IAM ロールに S3 への PutObject および GetObject の権限を与えることで、Amazon S3 へのユーザーアクセスを制御することができます。

今回は ECS タスクロールに関しての詳細は割愛します。

# Paws::S3 について
https://metacpan.org/pod/Paws::S3
> Paws::S3 - Perl Interface to AWS Amazon Simple Storage Service

Paws::S3 は AWS API を用いて Amazon S3 にPutObject や GetObject などの操作を行うことができます。
AWS API については公式のドキュメントをご覧下さい。
https://docs.aws.amazon.com/AmazonS3/latest/API/Welcome.html

# 実行環境
MacBook Pro
OS: macOS Mojave
Perl v5.30.0

# 参考実装
module の install は carton install で行いました。

```:cpanfile
requires 'Paws', '== 0.42';
```

## Paws::S3->PutObject
https://metacpan.org/pod/Paws::S3#PutObject

```perl:put_object.pl
use strict;
use warnings;
use utf8;
use Paws;
use Paws::Net::Caller;
use Paws::Credential::Explicit;
use feature qw/say/;

# see
# https://docs.aws.amazon.com/AmazonS3/latest/dev/storage-class-intro.html
# https://docs.aws.amazon.com/AmazonS3/latest/dev/S3_ACLs_UsingACLs.html
my $AWS_S3_STORAGE_CLASS = 'STANDARD';
my $AWS_S3_ACL_SHORT     = 'private';

# create data
my $AWS_S3_CONTENT_TYPE  = 'text/plain';
my $content;
open my $fh, '>:utf8', \$content or die "Error:$!";
print $fh "Hey\n";
print $fh "Yo\n";
close $fh;

# for disable warnings "Paws::S3 is not stable / supported / entirely developed"
local $ENV{'PAWS_SILENCE_UNSTABLE_WARNINGS'} = 1;
my $s3 = Paws->service('S3',
    region       => "ap-northeast-1",
    max_attempts => 3,

    # caller default timeout => 60,
    # https://github.com/pplu/aws-sdk-perl/blob/95db4ae45612d9e9760bc15188d56bf59e7f5a8f/lib/Paws/Net/Caller.pm#L8-L14
    # caller       => $caller,

    # default: use of ECS task IAM Role
    # credentials  => $credentials,
);

eval {
    my $bucket = "test-bucket";
    my $key = "sample/test.txt"

    # result: https://metacpan.org/pod/Paws::S3::PutObjectOutput
    my $result = $s3->PutObject(
        Bucket       => $bucket,
        Key          => $key,
        Body         => $content,
        ContentType  => $AWS_S3_CONTENT_TYPE,
        ACL          => $AWS_S3_ACL_SHORT,
        StorageClass => $AWS_S3_STORAGE_CLASS,
    );
};
if (my $e = $@) {
    say "$e";
};

say "upload done";
```

## Paws::S3->GetObject
```perl:get_object.pl
use strict;
use warnings;
use utf8;
use Paws;
use Paws::Net::Caller;
use feature qw/say/;

# for disable warnings "Paws::S3 is not stable / supported / entirely developed"
local $ENV{'PAWS_SILENCE_UNSTABLE_WARNINGS'} = 1;

my $s3 = Paws->service('S3',
    region       => "ap-northeast-1",
    max_attempts => 3,

    # caller default timeout => 60,
    # https://github.com/pplu/aws-sdk-perl/blob/95db4ae45612d9e9760bc15188d56bf59e7f5a8f/lib/Paws/Net/Caller.pm#L8-L14
    # caller       => $caller,

    # default: use of ECS task IAM Role
    # credentials  => $credentials,
);

eval {
    my $bucket = "test-bucket";
    my $key = "sample/test.txt"

    # result: https://metacpan.org/pod/Paws::S3::GetObjectOutput
    my $result = $s3->GetObject(
        Bucket => $bucket,
        Key    => $key,
    );

    # output:
    # Hey
    # Yo
    say $result->Body;
};
if (my $e = $@) {
    say "$e";
};
```

# さいごに
Paws::S3 の method 名や param は Amazon S3 API とほぼ同じように作られているので、 PascalCase で作られているようです。
- https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html
- https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObject.html


また、Paws module の package が Paws 単位ではあるが、様々な AWS の API に対応しているようで、

```:cpanfile
requires 'Paws', '== 0.42';
```

で install するとたくさんの module が入ってくるので、install に時間がかかりました。

※ docker 内で install したところ 4 分くらいかかった...

```
11 DONE fetch     (243.344sec) Paws-0.42
```

---

以上になります。
明日は karupanerura さんです！