Skip to content

Commit 56c8953

Browse files
authored
Add all current AWS models (#2)
1 parent e2a81c3 commit 56c8953

File tree

407 files changed

+3256229
-8
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

407 files changed

+3256229
-8
lines changed

.scripts/convert_models

Lines changed: 254 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,254 @@
1+
#!/usr/bin/env python3
2+
3+
from pathlib import Path
4+
import json
5+
from typing import Dict, Optional
6+
from dataclasses import dataclass
7+
import logging
8+
import argparse
9+
import sys
10+
11+
12+
SERVICE_TYPE = "service"
13+
SERVICE_TRAIT = "aws.api#service"
14+
15+
logger = logging.getLogger(__name__)
16+
logging.basicConfig(
17+
level=logging.INFO,
18+
format="%(asctime)s.%(msecs)03d - %(levelname)s - %(message)s",
19+
datefmt="%Y-%m-%dT%H:%M:%S",
20+
)
21+
22+
23+
@dataclass
24+
class ModelInfo:
25+
model: dict
26+
sdk_id: str # the sdk-id from the model
27+
service: tuple[str, dict] # the service shape id and service shape
28+
29+
30+
def transform_sdk_id(sdk_id: str) -> str:
31+
"""Transform the sdkId to lower-case and spaces replaced with hyphens.
32+
33+
For example, 'API Gateway' would become 'api-gateway'.
34+
35+
:param sdk_id: the sdkId
36+
:return: the lowercased 'sdkId' with spaces replaced with hypens
37+
"""
38+
39+
return sdk_id.lower().replace(" ", "-")
40+
41+
42+
def load_overrides(override_path: Optional[Path]) -> Dict[str, dict]:
43+
"""
44+
Load model overrides from a file.
45+
46+
The override file should be structured as:
47+
{
48+
"<sdkId>": {
49+
"shapes": {
50+
"com.amazonaws.xyz#Xyz": ...
51+
},
52+
...
53+
}
54+
}
55+
56+
:param override_path: Path to JSON file containing overrides
57+
:return: Dictionary of overrides keyed by sdkId
58+
"""
59+
60+
if not override_path or not override_path.is_file:
61+
return {}
62+
63+
try:
64+
return json.loads(override_path.read_text(encoding="utf-8"))
65+
except Exception:
66+
logger.error(f"Failed to load overrides from {override_path}", exc_info=True)
67+
raise
68+
69+
70+
def apply_overrides(model_json: dict, overrides: dict) -> dict:
71+
"""
72+
Apply overrides to the model JSON by deep merging.
73+
74+
:param model_json: Original model JSON
75+
:param overrides: Override values to apply
76+
:return: Updated model JSON with overrides applied
77+
"""
78+
79+
def deep_merge(base: dict, update: dict) -> dict:
80+
for key, value in update.items():
81+
if key in base and isinstance(base[key], dict) and isinstance(value, dict):
82+
deep_merge(base[key], value)
83+
else:
84+
base[key] = value
85+
return base
86+
87+
return deep_merge(model_json.copy(), overrides)
88+
89+
90+
def handle_model(model_path: Path, overrides: Dict[str, dict] = None) -> ModelInfo:
91+
"""
92+
Parse and process a model.json file.
93+
94+
:param model_path: Path to the model.json file
95+
:param overrides: Optional dictionary of overrides keyed by SDK ID
96+
:return: Model with processed data
97+
"""
98+
99+
# Load and parse the model file
100+
smithy_model_json = json.loads(model_path.read_text(encoding="utf-8"))
101+
102+
# Find the service shape
103+
service_shape = None
104+
sdk_id = None
105+
106+
for shape_id, shape in smithy_model_json.get("shapes", {}).items():
107+
if shape.get("type") == "service":
108+
service_shape = shape
109+
service_shape_id = shape_id
110+
# Get the 'sdkId' for the service
111+
sdk_id = shape.get("traits", {}).get("aws.api#service", {}).get("sdkId")
112+
break
113+
114+
if None in (service_shape, service_shape_id, sdk_id):
115+
raise ValueError("Could not find service shape with sdkId in model")
116+
117+
# Apply any overrides for this service
118+
if overrides and sdk_id in overrides:
119+
logger.info(f" Applying overrides for SDK ID: {sdk_id}")
120+
smithy_model_json = apply_overrides(smithy_model_json, overrides[sdk_id])
121+
122+
# Re-fetch service shape as it might have been modified
123+
for shape_id, shape in smithy_model_json.get("shapes", {}).items():
124+
if shape.get("type") == "service":
125+
service_shape = shape
126+
service_shape_id = shape_id
127+
break
128+
129+
return ModelInfo(
130+
model=smithy_model_json,
131+
sdk_id=sdk_id,
132+
service=(service_shape_id, service_shape),
133+
)
134+
135+
136+
def process_models(
137+
source_dir: Path, dest_dir: Path, override_path: Optional[Path] = None
138+
) -> None:
139+
"""
140+
Walk through source directory and process all model.json files.
141+
142+
:param source_dir: Path to directory containing source models
143+
:param dest_dir: Path to directory where transformed models should be written
144+
:param override_path: Optional path to model overrides file
145+
"""
146+
147+
logger.info(f"Processing models from {source_dir}")
148+
logger.info(f"Writing output to {dest_dir}")
149+
150+
# Load overrides if provided
151+
overrides = load_overrides(override_path)
152+
if overrides:
153+
logger.info(f"Loaded overrides for services: {', '.join(overrides.keys())}")
154+
155+
# Ensure source directory exists
156+
if not source_dir.is_dir():
157+
raise FileNotFoundError(f"Source directory not found: {source_dir}")
158+
159+
# Track success and failure counts
160+
processed = 0
161+
failed = 0
162+
163+
# Get all model.json files, there should be 1 per service
164+
for model_path in source_dir.rglob("model.json"):
165+
try:
166+
logger.info(f"Processing {model_path}")
167+
process_model(model_path, dest_dir, overrides)
168+
processed += 1
169+
170+
except Exception:
171+
logger.error(f"Failed to process {model_path}", exc_info=True)
172+
failed += 1
173+
174+
logger.info(
175+
f"Processing complete. Successfully processed: {processed}, Failed: {failed}"
176+
)
177+
if failed > 0:
178+
logger.warning("Some models failed to process. Check logs for details.")
179+
sys.exit(1)
180+
181+
182+
def process_model(input_path: Path, dest_dir: Path, overrides: Dict[str, dict]) -> None:
183+
"""
184+
Process a single model file and write the transformed version.
185+
186+
:param input_path: Path to the input model.json file
187+
:param dest_dir: Path to destination directory
188+
:param overrides: Dictionary of model overrides keyed by sdkId
189+
"""
190+
191+
logger.info(f" Input path: {input_path}")
192+
193+
try:
194+
# Process the model with overrides
195+
modelInfo = handle_model(input_path, overrides)
196+
197+
# Get the service version from the service shape
198+
service_shape_id, service_shape = modelInfo.service
199+
service_version = service_shape["version"]
200+
201+
# Create the service-id and file name
202+
transformed_sdk_id = transform_sdk_id(modelInfo.sdk_id)
203+
file_name = f"{transformed_sdk_id}-{service_version}.json"
204+
205+
# Create the new directory structure and file path
206+
output_path = (
207+
dest_dir / transformed_sdk_id / "service" / service_version / file_name
208+
)
209+
output_path.parent.mkdir(parents=True, exist_ok=True)
210+
211+
# Write the model
212+
output_path.write_text(json.dumps(modelInfo.model, indent=2), encoding="utf-8")
213+
214+
logger.info(f" SDK ID: {modelInfo.sdk_id}")
215+
logger.info(f" Service Version: {service_version}")
216+
logger.info(f" Output: {output_path}")
217+
logger.info("=" * 80)
218+
219+
except Exception as e:
220+
logger.error(f" Failed to process model: {str(e)}", exc_info=True)
221+
logger.info("=" * 80)
222+
raise
223+
224+
225+
if __name__ == "__main__":
226+
parser = argparse.ArgumentParser(
227+
description="Transform Smithy model.json files from source to destination directory."
228+
)
229+
230+
parser.add_argument(
231+
"--source-dir",
232+
"-s",
233+
type=Path,
234+
required=True,
235+
help="Source directory containing model.json files",
236+
)
237+
238+
parser.add_argument(
239+
"--dest-dir",
240+
"-d",
241+
type=Path,
242+
required=True,
243+
help="Destination directory for transformed models",
244+
)
245+
246+
parser.add_argument(
247+
"--overrides",
248+
"-o",
249+
type=Path,
250+
help="JSON file containing model overrides (keyed by `Sdk ID`)",
251+
)
252+
args = parser.parse_args()
253+
254+
process_models(args.source_dir, args.dest_dir, args.overrides)

.scripts/overrides.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"ACM PCA": {
3+
"shapes": {
4+
"com.amazonaws.acmpca#ACMPrivateCA": {
5+
"version": "2017-08-22"
6+
}
7+
}
8+
}
9+
}

.scripts/queries

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
2+
# Get the file path, shapeId, sdkId, and title for every service shape
3+
```
4+
find ../ -name "*-*.json" -exec jq '
5+
.shapes | to_entries[] |
6+
select(.value.type == "service") |
7+
{
8+
file: input_filename,
9+
shapeId: .key,
10+
sdkId: .value.traits."aws.api#service".sdkId,
11+
title: .value.traits."smithy.api#title"
12+
}
13+
' {} \; | jq -s '. | sort_by(.file)' > result.json
14+
```

README.md

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,46 @@
1-
## My Project
1+
# AWS API Models
22

3-
TODO: Fill this README out!
3+
> [!WARNING]
4+
> Currently, this repository is NOT updated daily, and therefore SHOULD NOT be considered the most up-to-date source of
5+
> AWS APIs.
6+
>
7+
> Additionally, this repository is not closely monitored, and the files here are generated from other sources. Because
8+
> of this, we are unable to accept pull requests and issues related to the service models should be directed to other
9+
> channels.
10+
>
11+
> For questions related to the AWS SDKs, please visit the respective repository for
12+
> [SDK specific support](https://github.com/aws). If you have an AWS support plan, you can create a new technical
13+
> support case in the [AWS Support Center](https://console.aws.amazon.com/support/home#/). Alternatively, you may
14+
> reach out to general AWS Support [here](https://aws.amazon.com/contact-us/)).
415
5-
Be sure to:
16+
This repository contains [Smithy](https://smithy.io/) models (in the
17+
[JSON AST](https://smithy.io/2.0/spec/json-ast.html) form) for all public AWS API services. Smithy is an open-source
18+
interface definition language, set of code generators, and developer tools used to generate code for web services and
19+
client SDKs from API models. At AWS, we use Smithy extensively to model our service APIs and provide the daily releases
20+
of the AWS SDKs and CLIs.
621

7-
* Change the title in this README
8-
* Edit your repository description on GitHub
22+
AWS API models can be helpful for a variety of uses cases such as building custom SDKs/CLIs SDKs for use with AWS or
23+
implementing MCP servers to interact with AWS services.
924

10-
## Security
1125

12-
See [CONTRIBUTING](CONTRIBUTING.md#security-issue-notifications) for more information.
26+
## Directory Structure
27+
28+
The AWS models repository contains:
29+
30+
* One top-level directory per service
31+
* Top-level service directories are named using the `<sdk-id>` of the service, where `<sdk-id>` is the value of the
32+
model's [`sdkId`](https://smithy.io/2.0/aws/aws-core.html#sdkid), lowercased and with spaces converted to hyphens
33+
* Each service directory contains one directory per `<version>` of the service, where `<version>` is the value of the
34+
service shape's [version property](https://smithy.io/2.0/spec/service-types.html#service)
35+
* Contained within a service-version directory, a model file named `<sdk-id>-<version>.json` will be present
36+
37+
38+
## Learn more
39+
40+
We invite you to learn more about the AWS preferred API modeling language at [smithy.io](https://smithy.io/).
41+
1342

1443
## License
1544

16-
This project is licensed under the Apache-2.0 License.
45+
This project is licensed under the [Apache-2.0 License](LICENSE).
1746

0 commit comments

Comments
 (0)