Moto. Mokaem AWS

Tests sind ein wesentlicher Bestandteil des Entwicklungsprozesses. Und manchmal müssen Entwickler die Tests lokal ausführen, bevor sie Änderungen committen.
Wenn die Anwendung verwendet Amazon Web Services, python einer Bibliothek moto eignet sich dafür ideal.
Moto. Mokaem AWS

Eine vollständige Liste der abgedeckten Ressourcen finden Sie hier.
Auf Github gibt es ein Repo Hugo Picadomoto-server. Ein fertiges Image, starten und nutzen. Der einzige Haken dabei ist, dass nach dem Start noch keine AWS Ressourcen erstellt wurden.

Nun, das lässt sich leicht beheben.

Da beim Start der Diensttyp angegeben werden muss (env Variable MOTO_SERVICE), müssen wir die Ressourcenerstellung beschreiben.

Ändern wir ein wenig start.sh:

Statt

moto_server $MOTO_SERVICE -H $MOTO_HOST -p $MOTO_PORT

Fügen wir ein:

if [ -f /opt/init/bootstrap.py ]; then
  moto_server $MOTO_SERVICE -H $MOTO_HOST -p $MOTO_PORT & (sleep 5 && echo "Bootstrapscript wird ausgeführt." && python /opt/init/bootstrap.py)
else
  moto_server $MOTO_SERVICE -H $MOTO_HOST -p $MOTO_PORT
fi
wait

Die endgültige Datei sieht wie folgt aus:

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

Wir erstellen ein neues Image und pushen es in unser Registry.

Als nächstes schreiben wir ein Initialisierungsskript für die Ressource, zum Beispiel SWF-Domain, unter Verwendung der Bibliothek zur Arbeit mit 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="Test SWF-Domain",
        workflowExecutionRetentionPeriodInDays="10"
    )
except ClientError as e:
    print "Domain existiert bereits: ", e.response.get("Error", {}).get("Code")

response = client.list_domains(
    registrationStatus='REGISTERED',
    maximumPageSize=123,
    reverseOrder=True|False
)

print 'Bereit'

Die Logik ist folgende:

  • Wir mounten unser Skript beim Start in /opt/init/bootstrap.py.
  • Wenn die Datei gemountet ist, wird sie ausgeführt.
  • Wenn die Datei nicht vorhanden ist, wird einfach der nackte moto-server gestartet.

Und mit einem einzigen Container kann man eine ganze Ressource mocken:

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

Probieren wir es im interaktiven Modus:

Moto. Mokaem AWS

Es funktioniert!

So können wir eine docker-compose.yml erstellen, die hilft, Zeit beim Testen von Änderungen zu sparen:

docker-compose.yml

version: '3'
services:
  s3:
    image: picadoh/motocker
    environment:
      - MOTO_SERVICE=s3
      - MOTO_HOST=10.0.1.2
    ports:
      - "5002:5000"
    networks:
      motonet:
        ipv4_address: 10.0.1.2
    volumes:
      - /tmp/bootstrap_s3.py:/opt/init/bootstrap.py
  swf:
    image: picadoh/motocker
    environment:
      - MOTO_SERVICE=swf
      - MOTO_HOST=10.0.1.3
    ports:
      - "5001:5000"
    networks:
      motonet:
        ipv4_address: 10.0.1.3
    volumes:
      - /tmp/bootstrap_swf.py:/opt/init/bootstrap.py
  ec2:
    image: picadoh/motocker
    environment:
      - MOTO_SERVICE=ec2
      - MOTO_HOST=10.0.1.4
    ports:
      - "5003:5000"
    networks:
      motonet:
        ipv4_address: 10.0.1.4
    volumes:
      - /tmp/bootstrap_ec2.py:/opt/init/bootstrap.py
networks:
  motonet:
    driver: bridge
    ipam:
      config:
        - subnet: 10.0.0.0/16

Es ist im Grunde nicht nur auf dem Laptop des Entwicklers möglich, einen solchen Ansatz zu verwenden. Vorabtests mit Mocks nach dem Build helfen, mögliche Probleme beim Start in dev* Umgebungen zu vermeiden.

Links:

Motocker-Repo — github.com/picadoh/motocker
Moto-Repo — github.com/spulec/moto
Boto3-Dokumentation — boto3.amazonaws.com/v1/documentation/api/latest/index.html

Quelle: habr.com

60GB SSD 8Gb DDR4