CLOVER🍀

That was when it all began.

LocalStackの提供するAWS CLIを使って、LocalStackを操作する

これは、なにをしたくて書いたもの?

LocalStackでAWS CLIを扱う時、--endpoint-url=...と指定する必要があるのが面倒です。

awsコマンドを使う時に、常に--endpoint-url=...となるようにエイリアスでもつけようかなと思っていたのですが、
LocalStackが提供しているAWS CLIを使うと良さそうなので使ってみました。

GitHub - localstack/awscli-local: 💲 "awslocal" - Thin wrapper around the "aws" command line interface for use with LocalStack

環境

今回の環境は、こちら。LocalStackも、LocalStackの提供するAWS CLIも、pipでインストールします。

$ python3 -V
Python 3.8.10


$ pip3 -V
pip 20.0.2 from /usr/lib/python3/dist-packages/pip (python 3.8)

LocalStackの提供するAWS CLIは、あくまで本家のAWS CLIのラッパーであるのでAWS CLI本体が必要です。

今回使うのはこちら。

$ aws --version
aws-cli/2.2.35 Python/3.8.8 Linux/5.4.0-81-generic exe/x86_64.ubuntu.20 prompt/off

LocalStackをインストール、起動する

まずはLocalStackがないと始まらないのでインストールします。

$ pip3 install localstack==0.12.17.5

バージョン。

$ localstack --version
0.12.17.5

起動。

$ localstack start

     __                     _______ __             __
    / /   ____  _________ _/ / ___// /_____ ______/ /__
   / /   / __ \/ ___/ __ `/ /\__ \/ __/ __ `/ ___/ //_/
  / /___/ /_/ / /__/ /_/ / /___/ / /_/ /_/ / /__/ ,<
 /_____/\____/\___/\__,_/_//____/\__/\__,_/\___/_/|_|

 💻 LocalStack CLI 0.12.17.5

[16:24:06] starting LocalStack in Docker mode 🐳                                                                                                               localstack.py:103
──────────────────────────────────────────────────────────────── LocalStack Runtime Log (press CTRL-C to quit) ─────────────────────────────────────────────────────────────────
['docker', 'run', '-it', '-e', 'TEST_AWS_ACCOUNT_ID=000000000000', '-e', 'DEFAULT_REGION=us-east-1', '-e', 'LOCALSTACK_HOSTNAME=localhost', '-e', 'DOCKER_HOST=unix:///var/run/docker.sock', '-e', 'HOST_TMP_FOLDER=/tmp/localstack', '--rm', '--privileged', '--name', 'localstack_main', '-p', '127.0.0.1:8080:8080', '-p', '127.0.0.1:4566:4566', '-p', '127.0.0.1:4571:4571', '-v', '/tmp/localstack:/tmp/localstack', '-v', '/var/run/docker.sock:/var/run/docker.sock', 'localstack/localstack']
Waiting for all LocalStack services to be ready
2021-09-04 07:24:07,601 CRIT Supervisor is running as root.  Privileges were not dropped because no user is specified in the config file.  If you intend to run as root, you can set user=root in the config file to avoid this message.
2021-09-04 07:24:07,604 INFO supervisord started with pid 15
2021-09-04 07:24:08,606 INFO spawned: 'infra' with pid 21
(. .venv/bin/activate; exec bin/localstack start --host)

     __                     _______ __             __
    / /   ____  _________ _/ / ___// /_____ ______/ /__
   / /   / __ \/ ___/ __ `/ /\__ \/ __/ __ `/ ___/ //_/
  / /___/ /_/ / /__/ /_/ / /___/ / /_/ /_/ / /__/ ,<
 /_____/\____/\___/\__,_/_//____/\__/\__,_/\___/_/|_|

 💻 LocalStack CLI 0.12.17.5

[07:24:09] starting LocalStack in host mode 💻                 localstack.py:101
──────────────── LocalStack Runtime Log (press CTRL-C to quit) ─────────────────
2021-09-04 07:24:10,539 INFO success: infra entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)

LocalStack version: 0.12.17.5
LocalStack Docker container id: efec1972ae42
LocalStack build date: 2021-09-03
LocalStack build git hash: 484d9d20

Waiting for all LocalStack services to be ready
Starting edge router (https port 4566)...
Starting mock ACM service on http port 4566 ...
2021-09-04T07:24:14:INFO:localstack.multiserver: Starting multi API server process on port 57135
[2021-09-04 07:24:14 +0000] [22] [INFO] Running on https://0.0.0.0:4566 (CTRL + C to quit)
2021-09-04T07:24:14:INFO:hypercorn.error: Running on https://0.0.0.0:4566 (CTRL + C to quit)
[2021-09-04 07:24:14 +0000] [22] [INFO] Running on http://0.0.0.0:57135 (CTRL + C to quit)
2021-09-04T07:24:14:INFO:hypercorn.error: Running on http://0.0.0.0:57135 (CTRL + C to quit)
Starting mock API Gateway service on http port 4566 ...
Starting mock CloudFormation service on http port 4566 ...
Starting mock Config Service service on http port 4566 ...
Starting mock CloudWatch service on http port 4566 ...
Starting mock DynamoDB service on http port 4566 ...
Starting mock DynamoDB Streams service on http port 4566 ...
Starting mock EC2 service on http port 4566 ...
Starting mock ES service on http port 4566 ...
Starting mock Firehose service on http port 4566 ...
Starting mock IAM service on http port 4566 ...
Starting mock STS service on http port 4566 ...
Starting mock Kinesis service on http port 4566 ...
Starting mock KMS service on http port 4566 ...
Starting mock Lambda service on http port 4566 ...
Starting mock CloudWatch Logs service on http port 4566 ...
Starting mock Redshift service on http port 4566 ...
Starting mock Route53 service on http port 4566 ...
Starting mock S3 service on http port 4566 ...
Starting mock Secrets Manager service on http port 4566 ...
Starting mock SES service on http port 4566 ...
Starting mock SNS service on http port 4566 ...
Starting mock SQS service on http port 4566 ...
Starting mock SSM service on http port 4566 ...
Starting mock Cloudwatch Events service on http port 4566 ...
Starting mock StepFunctions service on http port 4566 ...
Starting mock SWF service on http port 4566 ...
Starting mock Resource Groups Tagging API service on http port 4566 ...
Starting mock Resource Groups API service on http port 4566 ...
Starting mock Support service on http port 4566 ...
Waiting for all LocalStack services to be ready
Ready.
2021-09-04T07:24:24:INFO:bootstrap.py: Execution of "start_api_services" took 9440.04ms

awscli-localをインストールする

続けて、LocalStackの提供するAWS CLIをインストールします。

$ pip3 install awscli-local==0.15

これで、awslocalというコマンドが使えるようになります。

試しに、S3バケットを操作してみましょう。

バケットの作成。

$ awslocal s3 mb s3://test-bucket
make_bucket: test-bucket

ファイルを作成して

$ echo 'Hello World' > file.txt

アップロード。

$ awslocal s3 cp file.txt s3://test-bucket
upload: ./file.txt to s3://test-bucket/file.txt                   

確認。

$ awslocal s3 ls test-bucket
2021-09-04 16:31:49         12 file.txt


$ awslocal s3 cp s3://test-bucket/file.txt -
Hello World

OKそうですね。

LocalStackの提供するAWS CLIの正体

最初にも書きましたが、LocalStackの提供するAWS CLIは、本家のAWS CLIのラッパーです。

というか、AWS CLIそのものを外部プロセスで起動しようとします。

awscli-local/awslocal at 53876fbb7dcc75868402cc5593ab36db87c4c66d · localstack/awscli-local · GitHub

https://github.com/localstack/awscli-local/blob/53876fbb7dcc75868402cc5593ab36db87c4c66d/bin/awslocal#L63-L65

このため、AWS CLIがインストールされていないとプロセスの起動に失敗します。

Traceback (most recent call last):
  File "/path/to/bin/awslocal", line 93, in main
    raise
RuntimeError: No active exception to reraise

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/path/to/bin/awslocal", line 272, in <module>
    main()
  File "/path/to/bin/awslocal", line 96, in main
    return run_as_separate_process()
  File "/path/to/bin/awslocal", line 169, in run_as_separate_process
    run(cmd_args, env_dict)
  File "/path/to/bin/awslocal", line 63, in run
    process = subprocess.Popen(
  File "/usr/lib/python3.8/subprocess.py", line 858, in __init__
    self._execute_child(args, executable, preexec_fn, close_fds,
  File "/usr/lib/python3.8/subprocess.py", line 1704, in _execute_child
    raise child_exception_type(errno_num, err_msg, err_filename)
FileNotFoundError: [Errno 2] No such file or directory: 'aws'

Bash Completionを有効にする

これでawslocalコマンドが使えるようになりましたが、このままだとBash Completion(コマンド補完)が効きません。

というわけで、awslocalコマンドでも効くようにしておきます。

$ complete -C `which aws_completer` awslocal

これで、コマンド補完ができるようになりました、と。

$ awslocal s3 
cp       ls       mb       mv       presign  rb       rm       sync     website