-
Notifications
You must be signed in to change notification settings - Fork 15
Expand file tree
/
Copy pathtest_apigateway.py
More file actions
289 lines (233 loc) · 11.1 KB
/
test_apigateway.py
File metadata and controls
289 lines (233 loc) · 11.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
# Note: This file has been (partially or fully) generated by an AI agent.
import boto3
import pytest
from botocore.exceptions import ClientError
from localstack.aws.connect import connect_to
from localstack.utils.strings import short_uid
from aws_proxy.shared.models import ProxyConfig
def test_apigateway_rest_api_requests(start_aws_proxy, cleanups):
api_name_aws = f"test-api-aws-{short_uid()}"
# start proxy - forwarding all API Gateway requests
config = ProxyConfig(services={"apigateway": {"resources": ".*"}})
start_aws_proxy(config)
# create clients
region_name = "us-east-1"
apigw_client = connect_to(region_name=region_name).apigateway
apigw_client_aws = boto3.client("apigateway", region_name=region_name)
# create REST API in AWS
create_response_aws = apigw_client_aws.create_rest_api(
name=api_name_aws, description="Test API for proxy testing"
)
api_id_aws = create_response_aws["id"]
cleanups.append(lambda: apigw_client_aws.delete_rest_api(restApiId=api_id_aws))
# assert that local call for this API is proxied
get_api_local = apigw_client.get_rest_api(restApiId=api_id_aws)
get_api_aws = apigw_client_aws.get_rest_api(restApiId=api_id_aws)
assert get_api_local["name"] == get_api_aws["name"] == api_name_aws
assert get_api_local["id"] == get_api_aws["id"] == api_id_aws
# negative test: verify that requesting a non-existent API fails
with pytest.raises(ClientError) as ctx:
apigw_client_aws.get_rest_api(restApiId="nonexistent123")
assert ctx.value.response["Error"]["Code"] == "NotFoundException"
# list APIs from AWS should include the created API
apis_aws = apigw_client_aws.get_rest_apis()
aws_api_ids = [api["id"] for api in apis_aws.get("items", [])]
assert api_id_aws in aws_api_ids
# update API description via LocalStack client (should proxy to AWS)
updated_description = "Updated description via proxy"
apigw_client.update_rest_api(
restApiId=api_id_aws,
patchOperations=[
{"op": "replace", "path": "/description", "value": updated_description}
],
)
# verify update is reflected in AWS
get_api_aws = apigw_client_aws.get_rest_api(restApiId=api_id_aws)
assert get_api_aws["description"] == updated_description
def test_apigateway_resources_and_methods(start_aws_proxy, cleanups):
api_name_aws = f"test-api-resources-{short_uid()}"
# start proxy - forwarding all API Gateway requests
config = ProxyConfig(services={"apigateway": {"resources": ".*"}})
start_aws_proxy(config)
# create clients
region_name = "us-east-1"
apigw_client = connect_to(region_name=region_name).apigateway
apigw_client_aws = boto3.client("apigateway", region_name=region_name)
# create REST API in AWS
create_response_aws = apigw_client_aws.create_rest_api(name=api_name_aws)
api_id_aws = create_response_aws["id"]
cleanups.append(lambda: apigw_client_aws.delete_rest_api(restApiId=api_id_aws))
# get root resource from AWS
resources_response = apigw_client_aws.get_resources(restApiId=api_id_aws)
root_resource_id = resources_response["items"][0]["id"]
# create a new resource via AWS client
resource_response = apigw_client_aws.create_resource(
restApiId=api_id_aws, parentId=root_resource_id, pathPart="users"
)
resource_id = resource_response["id"]
# create a method via AWS client
apigw_client_aws.put_method(
restApiId=api_id_aws,
resourceId=resource_id,
httpMethod="GET",
authorizationType="NONE",
)
# verify method exists via LocalStack client (should proxy to AWS)
method_local = apigw_client.get_method(
restApiId=api_id_aws, resourceId=resource_id, httpMethod="GET"
)
assert method_local["httpMethod"] == "GET"
assert method_local["authorizationType"] == "NONE"
# create method response via AWS client
apigw_client_aws.put_method_response(
restApiId=api_id_aws,
resourceId=resource_id,
httpMethod="GET",
statusCode="200",
)
# verify method response via LocalStack (proxied)
method_response_local = apigw_client.get_method_response(
restApiId=api_id_aws, resourceId=resource_id, httpMethod="GET", statusCode="200"
)
assert method_response_local["statusCode"] == "200"
# create integration via AWS client
apigw_client_aws.put_integration(
restApiId=api_id_aws,
resourceId=resource_id,
httpMethod="GET",
type="MOCK",
requestTemplates={"application/json": '{"statusCode": 200}'},
)
# verify integration via LocalStack (proxied)
integration_local = apigw_client.get_integration(
restApiId=api_id_aws, resourceId=resource_id, httpMethod="GET"
)
assert integration_local["type"] == "MOCK"
# delete method via AWS client
apigw_client_aws.delete_method(
restApiId=api_id_aws, resourceId=resource_id, httpMethod="GET"
)
# verify method is deleted via LocalStack (proxied)
with pytest.raises(ClientError) as ctx:
apigw_client.get_method(
restApiId=api_id_aws, resourceId=resource_id, httpMethod="GET"
)
assert ctx.value.response["Error"]["Code"] in ["NotFoundException", "404"]
def test_apigateway_deployments(start_aws_proxy, cleanups):
api_name_aws = f"test-api-deploy-{short_uid()}"
# start proxy - forwarding all API Gateway requests
config = ProxyConfig(services={"apigateway": {"resources": ".*"}})
start_aws_proxy(config)
# create clients
region_name = "us-east-1"
apigw_client = connect_to(region_name=region_name).apigateway
apigw_client_aws = boto3.client("apigateway", region_name=region_name)
# create REST API in AWS
create_response_aws = apigw_client_aws.create_rest_api(name=api_name_aws)
api_id_aws = create_response_aws["id"]
cleanups.append(lambda: apigw_client_aws.delete_rest_api(restApiId=api_id_aws))
# get root resource and create a simple method
resources_response = apigw_client_aws.get_resources(restApiId=api_id_aws)
root_resource_id = resources_response["items"][0]["id"]
apigw_client_aws.put_method(
restApiId=api_id_aws,
resourceId=root_resource_id,
httpMethod="GET",
authorizationType="NONE",
)
apigw_client_aws.put_integration(
restApiId=api_id_aws,
resourceId=root_resource_id,
httpMethod="GET",
type="MOCK",
)
# create deployment via LocalStack client (should proxy to AWS)
stage_name = "test"
deployment_response = apigw_client.create_deployment(
restApiId=api_id_aws, stageName=stage_name, description="Test deployment"
)
deployment_id = deployment_response["id"]
# verify deployment exists in AWS
deployment_aws = apigw_client_aws.get_deployment(
restApiId=api_id_aws, deploymentId=deployment_id
)
assert deployment_aws["id"] == deployment_id
assert deployment_aws["description"] == "Test deployment"
# get stage via LocalStack client
stage_local = apigw_client.get_stage(restApiId=api_id_aws, stageName=stage_name)
stage_aws = apigw_client_aws.get_stage(restApiId=api_id_aws, stageName=stage_name)
assert stage_local["stageName"] == stage_aws["stageName"] == stage_name
assert stage_local["deploymentId"] == stage_aws["deploymentId"] == deployment_id
# list deployments via AWS client (verify deployment exists)
deployments_aws = apigw_client_aws.get_deployments(restApiId=api_id_aws)
aws_deployment_ids = [d["id"] for d in deployments_aws.get("items", [])]
assert deployment_id in aws_deployment_ids
def test_apigateway_read_only_mode(start_aws_proxy, cleanups):
api_name_aws = f"test-api-readonly-{short_uid()}"
# create REST API in AWS first (before starting proxy)
region_name = "us-east-1"
apigw_client_aws = boto3.client("apigateway", region_name=region_name)
create_response_aws = apigw_client_aws.create_rest_api(name=api_name_aws)
api_id_aws = create_response_aws["id"]
cleanups.append(lambda: apigw_client_aws.delete_rest_api(restApiId=api_id_aws))
# start proxy in read-only mode
config = ProxyConfig(
services={"apigateway": {"resources": ".*", "read_only": True}}
)
start_aws_proxy(config)
# create LocalStack client
apigw_client = connect_to(region_name=region_name).apigateway
# read operations should work (proxied to AWS)
get_api_local = apigw_client.get_rest_api(restApiId=api_id_aws)
assert get_api_local["name"] == api_name_aws
assert get_api_local["id"] == api_id_aws
# verify the API can also be read directly from AWS
get_api_aws = apigw_client_aws.get_rest_api(restApiId=api_id_aws)
assert get_api_local["name"] == get_api_aws["name"]
# write operations should fail (not allowed in read-only mode)
# In read-only mode, the API exists in AWS but LocalStack should not
# allow write operations to be proxied
original_description = get_api_aws.get("description", "")
# Attempt write operation - should be blocked in read-only mode
with pytest.raises(Exception):
apigw_client.update_rest_api(
restApiId=api_id_aws,
patchOperations=[
{
"op": "replace",
"path": "/description",
"value": "Should not reach AWS",
}
],
)
# Verify the API description was not changed in AWS
get_api_aws_after = apigw_client_aws.get_rest_api(restApiId=api_id_aws)
assert get_api_aws_after.get("description", "") == original_description
def test_apigateway_selective_resource_matching(start_aws_proxy, cleanups):
api_name_aws = f"test-api-selective-{short_uid()}"
# start proxy - forwarding all API Gateway requests
config = ProxyConfig(services={"apigateway": {"resources": ".*"}})
start_aws_proxy(config)
# create clients
region_name = "us-east-1"
apigw_client = connect_to(region_name=region_name).apigateway
apigw_client_aws = boto3.client("apigateway", region_name=region_name)
# create API in AWS
create_response_aws = apigw_client_aws.create_rest_api(name=api_name_aws)
api_id_aws = create_response_aws["id"]
cleanups.append(lambda: apigw_client_aws.delete_rest_api(restApiId=api_id_aws))
# accessing the API via LocalStack should be proxied
get_api_local = apigw_client.get_rest_api(restApiId=api_id_aws)
assert get_api_local["name"] == api_name_aws
# verify the API details match between LocalStack and AWS
get_api_aws = apigw_client_aws.get_rest_api(restApiId=api_id_aws)
assert get_api_local["id"] == get_api_aws["id"]
assert get_api_local["name"] == get_api_aws["name"]
# negative test: verify that requesting a non-existent API ID fails
with pytest.raises(ClientError) as ctx:
apigw_client_aws.get_rest_api(restApiId="nonexistent123456")
assert ctx.value.response["Error"]["Code"] == "NotFoundException"
# verify LocalStack also returns error for non-existent API
with pytest.raises(ClientError) as ctx:
apigw_client.get_rest_api(restApiId="nonexistent123456")
assert ctx.value.response["Error"]["Code"] in ["NotFoundException", "404"]