[JAWS-UG CLI] S3:#1 ハイレベルS3コマンドを使ってみる (バケットの作成から静的Webホスティング、削除まで)

このハンズオンでは、ハイレベルS3コマンドの全てを使ってみます。

ハイレベルS3コマンドが使えれば、S3をNASのように利用できるようになるので非常に便利です。 
(但し、ファイル総数が1000を超える場合は、急速にパフォーマンスが低下するらしいのでご注意ください。)


ハイレベルS3コマンド: http://docs.aws.amazon.com/cli/latest/reference/s3/

* cp
* ls
* mb
* mv
* rb
* rm
* sync
* website


前提条件
========

* [JAWS-UG CLI] 総合案内: http://qiita.com/tcsh/items/14c3278f69ab073afe0f を確認して、必要な手順を終えていること。

S3への権限
----------------------

S3に対してフルアクセス権限があること。


AWS CLI
-------------------

以下のバージョンで動作確認済

* AWS CLI 1.10.0
* AWS CLI 1.7.39
* AWS CLI 1.7.12

```bash:コマンド:
aws --version
```

```text:結果(例):
aws-cli/1.10.0 Python/2.7.5 Darwin/13.4.0 botocore/1.3.22
```



0. 準備
=======



0.1. リージョンの決定
---------------------

作成するS3バケットのリージョンを決めます。

(カレントユーザが利用するカレントリージョンも切り変わります。)

```bash:変数の設定:
export AWS_DEFAULT_REGION='ap-northeast-1'
```


0.2. 変数の確認
---------------

プロファイルとリージョンが想定のものになっていることを確認します。

```bash:変数の確認:
aws configure list
```

```text:結果(例):
            Name                    Value             Type    Location
            ----                    -----             ----    --------
         profile        s3Full-prjZ-mbp13              env    AWS_DEFAULT_PROFILE
      access_key     ****************LOAQ shared-credentials-file
      secret_key     ****************I1O1 shared-credentials-file
          region           ap-northeast-1              env    AWS_DEFAULT_REGION
```

AssumeRoleを利用している場合はprofileが '\<not set\>'と表示されます。
それ以外のときにprofileが '\<not set\>'  と表示される場合は、以下を実行してください。

```bash:コマンド:
export AWS_DEFAULT_PROFILE=<IAMユーザ名>
```


1. S3バケットの作成
===================


1.1. 組織名/プロジェクト名の決定
--------------------------------

S3バケット名を決めます。
(英小文字と数字が使えます。S3上でユニークである必要があります。英大文字は使用できません。)

ここでは、組織名-プロジェクト名-handsonという名前のバケットを利用するものとします。


```bash:コマンド:
ORG_NAME=<組織名>
PRJ_NAME=<プロジェクト名>
```

```bash:コマンド(例):
S3_BUCKET_NAME="${ORG_NAME}-handson-$(date +%Y%m%d%H%M)" \
  && echo ${S3_BUCKET_NAME}
```

1.2. 同名バケットの不存在確認
-----------------------------

```bash:コマンド:
aws s3 ls s3://${S3_BUCKET_NAME}/
```

```text:結果:
A client error (NoSuchBucket) occurred when calling the ListObjects operation: The specified bucket does not exist
```


1.3. バケット作成 (mb)
----------------------

```bash:変数の確認:
cat << ETX

        S3_BUCKET_NAME: ${S3_BUCKET_NAME}

ETX
```

バケットを作成します。

```bash:コマンド:
aws s3 mb s3://${S3_BUCKET_NAME}
```


```text:結果(例):
make_bucket: s3://corp-handson-2016020118
```

1.4. バケットの確認 (ls)
------------------------

バケットを表示します。

```bash:コマンド:
aws s3 ls | grep ${S3_BUCKET_NAME}
```

```text:結果(例):
2015-03-26 13:44:51 corp-handson-2016020118
```


1.5. ファイルの確認 (ls)
----------------------------

バケットの中身を表示すると、まだファイルがありません。

```bash:コマンド:
aws s3 ls s3://${S3_BUCKET_NAME}/
```

```text:結果(例):
(戻り値なし)
```


2. S3にファイル保存
===================


2.1. サンプルファイルの準備
---------------------------

```bash:コマンド:
FILE_LOCAL='handson.data'
touch ${FILE_LOCAL}
```


2.2. ファイルをアップロード (cp)
--------------------------------

```bash:変数の確認:
cat << ETX

        S3_BUCKET_NAME: ${S3_BUCKET_NAME}
        FILE_LOCAL:     ${FILE_LOCAL}

ETX
```

```bash:コマンド:
aws s3 cp ${FILE_LOCAL} s3://${S3_BUCKET_NAME}/
```

```text:結果(例):
upload: ./handson.data to s3://corp-handson-2016020118/handson.data
```


2.3. 確認 (ls)
--------------

バケットの中身を表示すると、転送されたファイルがあることがわかります。

```bash:コマンド:
aws s3 ls s3://${S3_BUCKET_NAME}/
```

```text:結果(例):
2015-03-26 13:45:16        0 handson.data
```


3. ファイルを新規フォルダに置く場合 (cp)
========================================

3.1. フォルダ名の決定
--------------------------------

```bash:コマンド:
S3_PATH='dir1'
```

3.2. ファイルをアップロード (cp)
--------------------------------

```bash:変数の確認:
cat << ETX

        FILE_LOCAL:     ${FILE_LOCAL}
        S3_BUCKET_NAME: ${S3_BUCKET_NAME}
        S3_PATH:        ${S3_PATH}

ETX
```

```bash:コマンド:
aws s3 cp ${FILE_LOCAL} s3://${S3_BUCKET_NAME}/${S3_PATH}/
```

```text:結果(例):
upload: ./handson.data to s3://corp-handson-2016020118/dir1/handson.data
```


4. ファイルのダウンロード (cp)
==============================

```bash:コマンド:
S3_OBJ='handson.data'
FILE_LOCAL='local.data'
```

```bash:変数の確認:
cat << ETX

        S3_BUCKET_NAME: ${S3_BUCKET_NAME}
        S3_OBJ:         ${S3_OBJ}
        FILE_LOCAL:     ${FILE_LOCAL}

ETX
```

```bash:コマンド:
aws s3 cp s3://${S3_BUCKET_NAME}/${S3_OBJ} ${FILE_LOCAL}
```

```text:結果(例):
download: s3://corp-handson-2016020118/handson.data to ./local.data
```

確認

```bash:コマンド:
ls ${FILE_LOCAL}
```

```text:結果:
local.data
```


5. ファイルの移動 (mv)
======================

```bash:コマンド:
S3_BUCKET_NAME_SRC=${S3_BUCKET_NAME}
S3_BUCKET_NAME_DST=${S3_BUCKET_NAME}
S3_OBJ_SRC=dir1/handson.data
S3_OBJ_DST=dir2/handson2.data
```

```bash:変数の確認:
cat << ETX

        S3_BUCKET_NAME_SRC: ${S3_BUCKET_NAME_SRC}
        S3_BUCKET_NAME_DST: ${S3_BUCKET_NAME_DST}
        S3_OBJ_SRC:         ${S3_OBJ_SRC}
        S3_OBJ_DST:         ${S3_OBJ_DST}

ETX
```

```bash:コマンド:
aws s3 mv s3://${S3_BUCKET_NAME_SRC}/${S3_OBJ_SRC} s3://${S3_BUCKET_NAME_DST}/${S3_OBJ_DST}
```

```text:結果(例):
move: s3://corp-handson-2016020118/dir1/handson.data to s3://corp-handson-2016020118/dir2/handson2.data
```

```bash:コマンド:
aws s3 ls s3://${S3_BUCKET_NAME_SRC}/${S3_OBJ_SRC}
```

```text:結果(例):
(戻り値なし)
```

```bash:コマンド:
aws s3 ls s3://${S3_BUCKET_NAME_DST}/${S3_OBJ_DST}
```

```text:結果(例):
2015-03-08 15:46:31          0 handson2.data
```


6. ファイルの削除 (rm)
==========================

```bash:コマンド:
S3_OBJ=${S3_OBJ_DST}
```

```bash:変数の確認:
cat << ETX

        S3_BUCKET_NAME: ${S3_BUCKET_NAME}
        S3_OBJ:         ${S3_OBJ}

ETX
```

```bash:コマンド:
aws s3 ls s3://${S3_BUCKET_NAME}/${S3_OBJ}
```

```text:結果(例):
2015-03-08 15:46:31          0 handson2.data
```

```bash:コマンド:
aws s3 rm s3://${S3_BUCKET_NAME}/${S3_OBJ}
```

```text:結果(例):
delete: s3://corp-handson-2016020118/dir2/handson2.data
```


7. バケットの同期 (sync)
========================


7.1. コンテンツの用意
---------------------

(gitが使える場合)

```bash:コマンド:
git clone https://github.com/opelab/jawsug-cli-sample-web.git && cd jawsug-cli-sample-web
```

```text:結果:
      Cloning into 'jawsug-cli-sample-web'...
      remote: Counting objects: 5, done.
      remote: Total 5 (delta 0), reused 0 (delta 0), pack-reused 5
      Unpacking objects: 100% (5/5), done.
      Checking connectivity... done.
```


```bash:コマンド:
ls
```

```text:結果:
error.html  img.jpg         index.html
```

(gitが使えない場合)

http://jawsug-cli.s3-website-ap-northeast-1.amazonaws.com/jawsug-cli-sample-web.zip を取得して、解凍し、解凍後のディレクトリにcdコマンドで移動してください。


7.2. コンテンツの同期
---------------------

クライアントPCに保存してあるサンプルコンテンツを、先程作成したコンテンツ公開用のS3バケットに同期します。

```bash:変数の確認:
cat << ETX

        S3_BUCKET_NAME: ${S3_BUCKET_NAME}

ETX
```

```bash:コマンド(gitの場合):
aws s3 sync . "s3://${S3_BUCKET_NAME}/" \
  --acl public-read \
  --exclude ".git*"
```

```text:結果(例):
      upload: ./index.html to s3://corp-handson-2016020118/index.html
      upload: ./img.jpg to s3://corp-handson-2016020118/img.jpg
      upload: ./error.html to s3://corp-handson-2016020118/error.html
```


7.3. 確認 (ls)
---------------------

バケットの中身を表示すると、同期されたファイルがあることがわかります。

```bash:コマンド:
aws s3 ls s3://${S3_BUCKET_NAME}/
```

```text:結果(例):
2015-03-09 19:52:13 186 error.html
2015-03-09 19:52:13 55560 img.jpg
2015-03-09 19:52:12 255 index.html
2015-03-09 19:46:25 0 test.data
```



8. website hosting (website)
============================

```bash:変数の確認:
cat << ETX

        S3_BUCKET_NAME: ${S3_BUCKET_NAME}

ETX
```

```bash:コマンド(通常):
aws s3 website "s3://${S3_BUCKET_NAME}" \
  --index-document index.html \
  --error-document error.html
```



```text:結果(例):
(戻り値なし)
```


9. ブラウザでコンテンツにアクセス
=================================

```bash:変数の確認:
cat << ETX

        AWS_DEFAULT_REGION: ${AWS_DEFAULT_REGION}
        S3_BUCKET_NAME: ${S3_BUCKET_NAME}

ETX
```

```bash:コマンド:
S3_BUCKET_ENDPOINT="${S3_BUCKET_NAME}.s3-website-`aws s3api get-bucket-location --bucket ${S3_BUCKET_NAME} --output text`.amazonaws.com" \
        && echo ${S3_BUCKET_ENDPOINT}
```

```text:結果(例):
      corp-handson-2016020118.s3-website-ap-northeast-1.amazonaws.com
```

Webブラウザで EndPoint が開ければOKです。


10. バケットを削除 (rb)
=======================


10.1. バケットを空にする
------------------------

事前にファイルを全て削除しておく必要があります。

```bash:変数の確認:
cat << ETX

        S3_BUCKET_NAME: ${S3_BUCKET_NAME}

ETX
```

```bash:コマンド:
aws s3 rm s3://${S3_BUCKET_NAME}/ \
  --recursive
```

```text:結果(例):
      delete: s3://opelab-prj04-handson/error.html
      delete: s3://opelab-prj04-handson/index.html
      delete: s3://opelab-prj04-handson/img.jpg
      delete: s3://opelab-prj04-handson/handson.data
```


10.2. バケットの削除
--------------------

```bash:変数の確認:
cat << ETX

        S3_BUCKET_NAME: ${S3_BUCKET_NAME}

ETX
```

```bash:コマンド:
aws s3 rb s3://${S3_BUCKET_NAME}
```

```text:結果(例):
remove_bucket: s3://corp-handson-2016020118/
```

```bash:コマンド:
aws s3 ls s3://${S3_BUCKET_NAME}/
```

```text:結果:
A client error (NoSuchBucket) occurred when calling the ListObjects operation: The specified bucket does not exist
```


完了
=======