Skip to content

Commit 659a64b

Browse files
authored
revamp the sample app with chaos api (#1)
1 parent 4672a70 commit 659a64b

File tree

3 files changed

+26
-33
lines changed

3 files changed

+26
-33
lines changed

README.md

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
# Simulating outages for local cloud apps with LocalStack!
1+
# Simulating outages for local cloud apps with LocalStack's Chaos API
22

3-
LocalStack's [Outages extension](https://pypi.org/project/localstack-extension-outages/) enables you to start a local outage, right on your developer machine. In this demo, we set up an HTTP CRUD API functioning as a Product Management System, and use the Outages extension to simulate an outage in the DynamoDB table. We'll further use `pytest` to test the application's behavior during the outage. For a more detailed walkthrough, check out our [Simulating Outages for Local Cloud Apps with LocalStack]() blog.
3+
LocalStack's [Chaos API](https://docs.localstack.cloud/user-guide/chaos-engineering/chaos-api/) enables you to simulate a local outage, right on your developer machine. In this demo, we set up an HTTP CRUD API functioning as a Product Management System, and use the Chaos API to simulate an outage in the DynamoDB table. We'll further use `pytest` to test the application's behavior during the outage.
44

55
## Architecture
66

@@ -41,9 +41,8 @@ docker-compose up
4141

4242
The Docker Compose configuration will:
4343

44-
* Install the Outages extension.
45-
* Create your cloud infrastructure.
4644
* Start the LocalStack container.
45+
* Create your cloud infrastructure.
4746

4847
### Test the infrastructure
4948

@@ -73,7 +72,7 @@ You can navigate to the [DynamoDB Resource Browser](https://app.localstack.cloud
7372
You can simulate an outage in your local DynamoDB table by running the following command:
7473

7574
```bash
76-
curl --location --request POST 'http://outages.localhost.localstack.cloud:4566/outages' \
75+
curl --location --request POST 'http://localhost.localstack.cloud:4566/_localstack/chaos/faults' \
7776
--header 'Content-Type: application/json' \
7877
--data '
7978
[
@@ -114,7 +113,7 @@ A DynamoDB error occurred. Message sent to queue.
114113
To stop the outage, run the following command:
115114

116115
```bash
117-
curl --location --request POST 'http://outages.localhost.localstack.cloud:4566/outages' \
116+
curl --location --request POST 'http://localhost.localstack.cloud:4566/_localstack/chaos/faults' \
118117
--header 'Content-Type: application/json' \
119118
--data '[]'
120119
```

docker-compose.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@ services:
1515
- LOCALSTACK_HOST=localstack
1616
- LAMBDA_DOCKER_NETWORK=ls_network
1717
- LOCALSTACK_AUTH_TOKEN=${LOCALSTACK_AUTH_TOKEN:?}
18-
- LAMBDA_RUNTIME_ENVIRONMENT_TIMEOUT=60
19-
- EXTENSION_AUTO_INSTALL=localstack-extension-outages
2018
- LAMBDA_RUNTIME_ENVIRONMENT_TIMEOUT=600
2119
volumes:
2220
- "./volume:/var/lib/localstack"

tests/test_outage.py

Lines changed: 21 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,42 +4,49 @@
44
import requests
55

66
# Replace with your LocalStack endpoint
7-
LOCALSTACK_ENDPOINT = "http://localhost:4566"
7+
LOCALSTACK_ENDPOINT = "http://localhost.localstack.cloud:4566"
8+
CHAOS_ENDPOINT = f"{LOCALSTACK_ENDPOINT}/_localstack/chaos/faults"
89

910
# Replace with your LocalStack DynamoDB table name
1011
DYNAMODB_TABLE_NAME = "Products"
1112

1213
# Replace with your Lambda function names
1314
LAMBDA_FUNCTIONS = ["add-product", "get-product", "process-product-events"]
1415

15-
1616
@pytest.fixture(scope="module")
1717
def dynamodb_resource():
1818
return boto3.resource("dynamodb", endpoint_url=LOCALSTACK_ENDPOINT)
1919

20-
2120
@pytest.fixture(scope="module")
2221
def lambda_client():
2322
return boto3.client("lambda", endpoint_url=LOCALSTACK_ENDPOINT)
2423

25-
2624
def test_dynamodb_table_exists(dynamodb_resource):
2725
tables = dynamodb_resource.tables.all()
2826
table_names = [table.name for table in tables]
2927
assert DYNAMODB_TABLE_NAME in table_names
3028

31-
3229
def test_lambda_functions_exist(lambda_client):
3330
functions = lambda_client.list_functions()["Functions"]
3431
function_names = [func["FunctionName"] for func in functions]
3532
assert all(func_name in function_names for func_name in LAMBDA_FUNCTIONS)
3633

37-
38-
def test_dynamodb_outage():
34+
def initiate_dynamodb_outage():
3935
outage_payload = [{"service": "dynamodb", "region": "us-east-1"}]
40-
requests.post(
41-
"http://outages.localhost.localstack.cloud:4566/outages", json=outage_payload
42-
)
36+
requests.post(CHAOS_ENDPOINT, json=outage_payload)
37+
return outage_payload
38+
39+
def check_outage_status(expected_status):
40+
outage_status = requests.get(CHAOS_ENDPOINT).json()
41+
assert outage_status == expected_status
42+
43+
def stop_dynamodb_outage():
44+
requests.post(CHAOS_ENDPOINT, json=[])
45+
check_outage_status([])
46+
47+
def test_dynamodb_outage(dynamodb_resource):
48+
# Initiate DynamoDB outage
49+
outage_payload = initiate_dynamodb_outage()
4350

4451
# Make a request to DynamoDB and assert an error
4552
url = "http://12345.execute-api.localhost.localstack.cloud:4566/dev/productApi"
@@ -52,31 +59,20 @@ def test_dynamodb_outage():
5259
}
5360

5461
response = requests.post(url, headers=headers, json=data)
55-
5662
assert "error" in response.text
5763

5864
# Check if outage is running
59-
outage_status = requests.get(
60-
"http://outages.localhost.localstack.cloud:4566/outages"
61-
).json()
62-
assert outage_payload == outage_status
65+
check_outage_status(outage_payload)
6366

6467
# Stop the outage
65-
requests.post("http://outages.localhost.localstack.cloud:4566/outages", json=[])
66-
67-
# Check if outage is stopped
68-
outage_status = requests.get(
69-
"http://outages.localhost.localstack.cloud:4566/outages"
70-
).json()
71-
assert not outage_status
68+
stop_dynamodb_outage()
7269

7370
# Wait for a few seconds
7471
time.sleep(60)
7572

7673
# Query if there are items in DynamoDB table
77-
dynamodb = boto3.resource("dynamodb", endpoint_url=LOCALSTACK_ENDPOINT)
78-
table = dynamodb.Table(DYNAMODB_TABLE_NAME)
74+
table = dynamodb_resource.Table(DYNAMODB_TABLE_NAME)
7975
response = table.scan()
8076
items = response["Items"]
8177
print(items)
82-
assert "Super Widget" in [item["name"] for item in items]
78+
assert any(item["name"] == "Super Widget" for item in items)

0 commit comments

Comments
 (0)