Π’Π΅ΡΡΠΎΠ²Π΅ΡΠ΅ ΡΠ° Π½Π΅ΡΠ°Π·ΡΠΈΠ²Π½ΠΎ ΡΠ²ΡΡΠ·Π°Π½ΠΈ Ρ ΠΏΡΠΎΡΠ΅ΡΠ° Π½Π° ΡΠ°Π·ΡΠ°Π±ΠΎΡΠΊΠ°. ΠΠΎΠ½ΡΠΊΠΎΠ³Π° ΡΠ°Π·ΡΠ°Π±ΠΎΡΡΠΈΡΠΈΡΠ΅ ΡΡΡΠ±Π²Π° Π΄Π° ΡΡΠ°ΡΡΠΈΡΠ°Ρ ΡΠ΅ΡΡΠΎΠ²Π΅ΡΠ΅ Π»ΠΎΠΊΠ°Π»Π½ΠΎ, ΠΏΡΠ΅Π΄ΠΈ Π΄Π° ΠΊΠΎΠΌΠΈΡΠ½Π°Ρ ΠΏΡΠΎΠΌΠ΅Π½ΠΈΡΠ΅.
ΠΠΊΠΎ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ΡΠΎ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° Amazon Web Services, python Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠ° moto ΠΏΠ΅ΡΡΠ΅ΠΊΡΠ½ΠΎ ΠΏΠΎΠ΄Ρ
ΠΎΠΆΠ΄Π° Π·Π° ΡΠΎΠ²Π°.

ΠΡΠ»Π½ΠΈΡΡ ΡΠΏΠΈΡΡΠΊ Ρ ΠΏΠΎΠΊΡΠΈΡΠΈ ΡΠ΅ΡΡΡΡΠΈ ΠΌΠΎΠΆΠ΅ Π΄Π° ΡΠ΅ Π²ΠΈΠ΄ΠΈ .
ΠΠ° Github ΠΈΠΌΠ° ΡΠ΅ΠΏΠΎΠ·ΠΈΡΠΎΡΠΈΠΉ Hugo Picado β . ΠΠΎΡΠΎΠ²ΠΈΡΡ ΠΎΠ±ΡΠ°Π·, ΡΡΠ°ΡΡΠΈΡΠ°ΠΉΡΠ΅ ΠΈ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΉΡΠ΅. ΠΠ΄ΠΈΠ½ΡΡΠ²Π΅Π½ΠΈΡΡ Π½ΡΠ°Π½Ρ Π΅, ΡΠ΅ ΡΠ»Π΅Π΄ ΡΡΠ°ΡΡΠΈΡΠ°Π½Π΅ΡΠΎ, Π²ΡΠ΅ ΠΎΡΠ΅ Π½ΡΠΌΠ° AWS ΡΠ΅ΡΡΡΡΠΈ ΡΠ°ΠΌ.
Π’ΠΎΠ²Π° Π΅ Π»Π΅ΡΠ½ΠΎ Π΄Π° ΡΠ΅ ΠΏΠΎΠΏΡΠ°Π²ΠΈ.
Π’ΡΠΉ ΠΊΠ°ΡΠΎ ΠΏΡΠΈ ΡΡΠ°ΡΡΠΈΡΠ°Π½Π΅ΡΠΎ Π΅ Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΠΎ Π΄Π° ΡΠ΅ Π·Π°Π΄Π°Π΄Π΅ ΡΠΈΠΏΡΡ ΡΡΠ»ΡΠ³Π° (env ΠΏΡΠΎΠΌΠ΅Π½Π»ΠΈΠ²Π° MOTO_SERVICE), ΠΎΡΡΠ°Π²Π° ΡΠ°ΠΌΠΎ Π΄Π° ΠΎΠΏΠΈΡΠ΅ΠΌ ΡΡΠ·Π΄Π°Π²Π°Π½Π΅ΡΠΎ Π½Π° ΡΠ΅ΡΡΡΡΠ°.
ΠΠ΅ΠΊΠΎ ΡΠ΅ ΠΏΡΠΎΠΌΠ΅Π½ΠΈΠΌ start.sh:
ΠΠΌΠ΅ΡΡΠΎ
moto_server $MOTO_SERVICE -H $MOTO_HOST -p $MOTO_PORT
ΠΠΌΡΠΊΠ²Π°ΠΌΠ΅:
if [ -f /opt/init/bootstrap.py ]; then
moto_server $MOTO_SERVICE -H $MOTO_HOST -p $MOTO_PORT & (sleep 5 && echo "ΠΠ·ΠΏΡΠ»Π½ΡΠ²Π° ΡΠΊΡΠΈΠΏΡ Π·Π° ΡΡΠ°ΡΡΠΈΡΠ°Π½Π΅." && python /opt/init/bootstrap.py)
else
moto_server $MOTO_SERVICE -H $MOTO_HOST -p $MOTO_PORT
fi
wait
ΠΡΠ°ΠΉΠ½ΠΈΡΡ ΡΠ°ΠΉΠ» ΠΈΠ·Π³Π»Π΅ΠΆΠ΄Π° ΡΠ°ΠΊΠ°:
start.sh
#!/bin/sh
# validate required input
if [ -z "$MOTO_SERVICE" ]; then
echo "Please define AWS service to run with Moto Server (e.g. s3, ec2, etc)"
exit 1
fi
# setting defaults for optional input
if [ -z "$MOTO_HOST" ]; then
MOTO_HOST="0.0.0.0"
fi
if [ -z "$MOTO_PORT" ]; then
MOTO_PORT="5000"
fi
echo "Starting service $MOTO_SERVICE at $MOTO_HOST:$MOTO_PORT"
if [ -f /opt/init/bootstrap.py ]; then
moto_server $MOTO_SERVICE -H $MOTO_HOST -p $MOTO_PORT & (sleep 5 && echo "Executing bootstrap script." && python /opt/init/bootstrap.py)
else
moto_server $MOTO_SERVICE -H $MOTO_HOST -p $MOTO_PORT
fi
# Prevent container from exiting when bootstrap.py finishing
waitΠ‘ΡΠ·Π΄Π°Π²Π°ΠΌΠ΅ Π½ΠΎΠ² ΠΎΠ±ΡΠ°Π· ΠΈ Π³ΠΎ ΠΊΠ°ΡΠ²Π°ΠΌΠ΅ Π² ΡΠ²ΠΎΡ ΡΠ΅Π³ΠΈΡΡΡΡ.
Π‘Π»Π΅Π΄Π²Π°ΡΠ°ΡΠ° ΡΡΡΠΏΠΊΠ° Π΅ Π΄Π° Π½Π°ΠΏΠΈΡΠ΅ΠΌ ΡΠΊΡΠΈΠΏΡ Π·Π° ΠΈΠ½ΠΈΡΠΈΠ°Π»ΠΈΠ·Π°ΡΠΈΡ Π½Π° ΡΠ΅ΡΡΡΡΠ°, Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ SWF Π΄ΠΎΠΌΠ΅ΠΉΠ½, ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΉΠΊΠΈ Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠ°ΡΠ° Π·Π° ΡΠ°Π±ΠΎΡΠ° Ρ AWS β boto3:
bootstrap_swf.py
import boto3
from botocore.exceptions import ClientError
import os
os.environ["AWS_ACCESS_KEY_ID"] = "fake"
os.environ["AWS_SECRET_ACCESS_KEY"] = "fake"
client = boto3.client('swf', region_name='us-west-2', endpoint_url='http://localhost:5000')
try:
client.register_domain(
name='test-swf-mock-domain',
description="Π’Π΅ΡΡΠΎΠ² SWF Π΄ΠΎΠΌΠ΅ΠΉΠ½",
workflowExecutionRetentionPeriodInDays="10"
)
except ClientError as e:
print "ΠΠΎΠΌΠ΅ΠΉΠ½ΡΡ Π²Π΅ΡΠ΅ ΡΡΡΠ΅ΡΡΠ²ΡΠ²Π°: ", e.response.get("Error", {}).get("Code")
response = client.list_domains(
registrationStatus='REGISTERED',
maximumPageSize=123,
reverseOrder=True|False
)
print 'ΠΠΎΡΠΎΠ²'
ΠΠΎΠ³ΠΈΠΊΠ°ΡΠ° Π΅ ΡΠ»Π΅Π΄Π½Π°ΡΠ°:
- ΠΡΠΈ ΡΡΠ°ΡΡΠΈΡΠ°Π½Π΅ ΠΌΠΎΠ½ΡΠΈΡΠ°ΠΌΠ΅ Π½Π°ΡΠΈΡ ΡΠΊΡΠΈΠΏΡ Π² /opt/init/bootstrap.py.
- ΠΠΊΠΎ ΡΠ°ΠΉΠ»ΡΡ Π΅ ΠΌΠΎΠ½ΡΠΈΡΠ°Π½ β ΡΠΎΠΉ ΡΠ΅ Π±ΡΠ΄Π΅ ΠΈΠ·ΠΏΡΠ»Π½Π΅Π½.
- ΠΠΊΠΎ ΡΠ°ΠΉΠ»Π° Π½ΡΠΌΠ° β ΠΏΡΠΎΡΡΠΎ ΡΠ΅ ΡΠ΅ ΡΡΠ°ΡΡΠΈΡΠ° ΡΠΈΡΡ moto-server.
Π ΠΌΠΎΠΆΠ΅ΡΠ΅ Π΄Π° ΠΌΠΎΠΊΠ½Π΅ΡΠ΅ ΡΠ΅Π»ΠΈΡ ΡΠ΅ΡΡΡΡ, ΡΡΠ°ΡΡΠΈΡΠ°ΠΉΠΊΠΈ ΡΠ°ΠΌΠΎ Π΅Π΄ΠΈΠ½ ΠΊΠΎΠ½ΡΠ΅ΠΉΠ½Π΅Ρ:
docker run --name swf -d
-e MOTO_SERVICE=swf
-e MOTO_HOST=0.0.0.0
-e MOTO_PORT=5000
-p 5001:5000
-v /tmp/bootstrap_swf.py:/opt/init/bootstrap.py
-i awesome-repo.com/moto-server:latest
Π’Π΅ΡΡΠ²Π°ΠΌΠ΅ Π² ΠΈΠ½ΡΠ΅ΡΠ°ΠΊΡΠΈΠ²Π΅Π½ ΡΠ΅ΠΆΠΈΠΌ:

Π Π°Π±ΠΎΡΠΈ!
ΠΠΎ ΡΠΎΠ·ΠΈ Π½Π°ΡΠΈΠ½ ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° ΡΡΠ·Π΄Π°Π΄Π΅ΠΌ docker-compose.yml, ΠΊΠΎΠΉΡΠΎ ΡΠ΅ ΡΠΏΠ΅ΡΡΠΈ Π²ΡΠ΅ΠΌΠ΅ ΠΏΡΠΈ ΡΠ΅ΡΡΠ²Π°Π½Π΅ΡΠΎ Π½Π° ΠΏΡΠΎΠΌΠ΅Π½ΠΈΡΠ΅:
docker-compose.yml
Π²Π΅ΡΡΠΈΡ: '3'
ΡΡΠ»ΡΠ³ΠΈ:
s3:
ΠΈΠ·ΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΠ΅: picadoh/motocker
ΡΡΠ΅Π΄Π°:
- MOTO_SERVICE=s3
- MOTO_HOST=10.0.1.2
ΠΏΠΎΡΡΠΎΠ²Π΅:
- "5002:5000"
ΠΌΡΠ΅ΠΆΠΈ:
motonet:
ipv4_address: 10.0.1.2
ΠΎΠ±Π΅ΠΌΠΈ:
- /tmp/bootstrap_s3.py:/opt/init/bootstrap.py
swf:
ΠΈΠ·ΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΠ΅: picadoh/motocker
ΡΡΠ΅Π΄Π°:
- MOTO_SERVICE=swf
- MOTO_HOST=10.0.1.3
ΠΏΠΎΡΡΠΎΠ²Π΅:
- "5001:5000"
ΠΌΡΠ΅ΠΆΠΈ:
motonet:
ipv4_address: 10.0.1.3
ΠΎΠ±Π΅ΠΌΠΈ:
- /tmp/bootstrap_swf.py:/opt/init/bootstrap.py
ec2:
ΠΈΠ·ΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΠ΅: picadoh/motocker
ΡΡΠ΅Π΄Π°:
- MOTO_SERVICE=ec2
- MOTO_HOST=10.0.1.4
ΠΏΠΎΡΡΠΎΠ²Π΅:
- "5003:5000"
ΠΌΡΠ΅ΠΆΠΈ:
motonet:
ipv4_address: 10.0.1.4
ΠΎΠ±Π΅ΠΌΠΈ:
- /tmp/bootstrap_ec2.py:/opt/init/bootstrap.py
ΠΌΡΠ΅ΠΆΠΈ:
motonet:
Π΄ΡΠ°ΠΉΠ²Π΅Ρ: ΠΌΠΎΡΡ
ipam:
ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΡ:
- ΠΏΠΎΠ΄ΡΠ΅Ρ: 10.0.0.0/16
ΠΠ°ΠΈΡΡΠΈΠ½Π°, Π½Π΅ ΡΠ°ΠΌΠΎ Π½Π° Π»Π°ΠΏΡΠΎΠΏΠ° Π½Π° ΡΠ°Π·ΡΠ°Π±ΠΎΡΡΠΈΠΊΠ° ΠΌΠΎΠΆΠ΅ Π΄Π° ΡΠ΅ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° ΡΠ°ΠΊΡΠ² ΠΏΠΎΠ΄Ρ ΠΎΠ΄. ΠΡΠ΅Π΄Π²Π°ΡΠΈΡΠ΅Π»Π½ΠΈΡΠ΅ ΡΠ΅ΡΡΠΎΠ²Π΅ Ρ ΠΌΠΎΠΊΠ° ΡΠ»Π΅Π΄ ΠΈΠ·Π³ΡΠ°ΠΆΠ΄Π°Π½Π΅ΡΠΎ ΡΠ΅ ΠΏΠΎΠΌΠΎΠ³Π½Π°Ρ Π·Π° ΠΈΠ·Π±ΡΠ³Π²Π°Π½Π΅ Π½Π° ΠΏΠΎΡΠ΅Π½ΡΠΈΠ°Π»Π½ΠΈ ΠΏΡΠΎΠ±Π»Π΅ΠΌΠΈ ΠΏΡΠΈ ΡΡΠ°ΡΡΠΈΡΠ°Π½Π΅ Π² dev* ΡΡΠ΅Π΄ΠΈ.
ΠΠΈΠ½ΠΊΠΎΠ²Π΅:
Motocker Ρ
ΡΠ°Π½ΠΈΠ»ΠΈΡΠ΅ β
Moto Ρ
ΡΠ°Π½ΠΈΠ»ΠΈΡΠ΅ β
Boto3 ΠΠΎΠΊΡΠΌΠ΅Π½ΡΠ°ΡΠΈΡ β
ΠΠ·ΡΠΎΡΠ½ΠΈΠΊ: habr.com
