@aws/nx-plugin-mcp 0.119.0 → 0.121.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/aws-nx-mcp.js +23 -35
- package/docs/guides/astro-docs.mdx +142 -0
- package/docs/guides/connection/py-agent-a2a.mdx +105 -0
- package/docs/guides/connection/py-agent-mcp.mdx +147 -0
- package/docs/guides/connection/react-agui.mdx +240 -0
- package/docs/guides/connection/react-fastapi.mdx +1476 -0
- package/docs/guides/connection/react-py-agent.mdx +198 -0
- package/docs/guides/connection/react-smithy.mdx +1355 -0
- package/docs/guides/connection/react-trpc.mdx +447 -0
- package/docs/guides/connection/react-ts-agent.mdx +198 -0
- package/docs/guides/connection/smithy-rdb.mdx +161 -0
- package/docs/guides/connection/trpc-rdb.mdx +127 -0
- package/docs/guides/connection/ts-agent-a2a.mdx +106 -0
- package/docs/guides/connection/ts-agent-mcp.mdx +144 -0
- package/docs/guides/connection/ts-agent-rdb.mdx +141 -0
- package/docs/guides/connection/ts-mcp-server-rdb.mdx +135 -0
- package/docs/guides/connection.mdx +126 -0
- package/docs/guides/docker-bundling.mdx +403 -0
- package/docs/guides/fastapi.mdx +509 -0
- package/docs/guides/license.mdx +293 -0
- package/docs/guides/nx-generator.mdx +588 -0
- package/docs/guides/py-agent.mdx +483 -0
- package/docs/guides/py-mcp-server.mdx +161 -0
- package/docs/guides/python-lambda-function.mdx +207 -0
- package/docs/guides/python-project.mdx +228 -0
- package/docs/guides/react-website-auth.mdx +216 -0
- package/docs/guides/react-website.mdx +421 -0
- package/docs/guides/runtime-config.mdx +312 -0
- package/docs/guides/terraform-project.mdx +317 -0
- package/docs/guides/trpc.mdx +816 -0
- package/docs/guides/ts-agent.mdx +436 -0
- package/docs/guides/ts-lambda-function.mdx +218 -0
- package/docs/guides/ts-mcp-server.mdx +169 -0
- package/docs/guides/ts-nx-plugin.mdx +159 -0
- package/docs/guides/ts-rdb.mdx +759 -0
- package/docs/guides/ts-smithy-api.mdx +661 -0
- package/docs/guides/typescript-infrastructure.mdx +408 -0
- package/docs/guides/typescript-project.mdx +312 -0
- package/docs/guides/workspace.mdx +181 -0
- package/docs/snippets/agent/architecture.mdx +72 -0
- package/docs/snippets/agent/bedrock-deployment.mdx +172 -0
- package/docs/snippets/agent/runtime-arn.mdx +64 -0
- package/docs/snippets/api/api-architecture.mdx +93 -0
- package/docs/snippets/api/api-choice-note.mdx +6 -0
- package/docs/snippets/api/cors-configuration-cdk-note.mdx +25 -0
- package/docs/snippets/api/cors-configuration-terraform-note.mdx +28 -0
- package/docs/snippets/api/shared-constructs.mdx +38 -0
- package/docs/snippets/api/type-safe-api-integrations.mdx +643 -0
- package/docs/snippets/api/waf-configuration.mdx +37 -0
- package/docs/snippets/connection/a2a-infrastructure.mdx +63 -0
- package/docs/snippets/connection/lambda-rdb-ssl-requirements.mdx +40 -0
- package/docs/snippets/connection/mcp-server-rdb-ssl-requirements.mdx +35 -0
- package/docs/snippets/connection/rdb-api-infrastructure.mdx +72 -0
- package/docs/snippets/connection/react-agent-infrastructure.mdx +61 -0
- package/docs/snippets/connection/strands-agent-rdb-ssl-requirements.mdx +35 -0
- package/docs/snippets/lambda-function/architecture.mdx +36 -0
- package/docs/snippets/lambda-function/deploying-your-function.mdx +118 -0
- package/docs/snippets/mcp/architecture.mdx +58 -0
- package/docs/snippets/mcp/assistant-docs.mdx +10 -0
- package/docs/snippets/mcp/bedrock-deployment.mdx +167 -0
- package/docs/snippets/mcp/config.mdx +13 -0
- package/docs/snippets/mcp/configuration-py.mdx +42 -0
- package/docs/snippets/mcp/configuration-ts.mdx +53 -0
- package/docs/snippets/mcp/observability.mdx +8 -0
- package/docs/snippets/mcp/shared-constructs.mdx +32 -0
- package/docs/snippets/pdk-migration/example/01-migrate-api.mdx +602 -0
- package/docs/snippets/pdk-migration/example/02-migrate-website.mdx +915 -0
- package/docs/snippets/pdk-migration/example/03-migrate-infra.mdx +161 -0
- package/docs/snippets/pdk-migration/example/04-deploy.mdx +229 -0
- package/docs/snippets/pdk-migration/faq/aws-arch.mdx +17 -0
- package/docs/snippets/pdk-migration/faq/cdk-graph.mdx +29 -0
- package/docs/snippets/pdk-migration/faq/infrastructure-python-java.mdx +19 -0
- package/docs/snippets/pdk-migration/faq/pdk-nag.mdx +15 -0
- package/docs/snippets/pdk-migration/faq/pipeline.mdx +15 -0
- package/docs/snippets/pdk-migration/faq/type-safe-api.mdx +310 -0
- package/docs/snippets/pdk-migration/faq/use-of-projen.mdx +15 -0
- package/docs/snippets/prerequisites.mdx +20 -0
- package/docs/snippets/required-prerequisites.mdx +12 -0
- package/docs/snippets/shared-constructs.mdx +40 -0
- package/docs/snippets/tools/acurl.mdx +73 -0
- package/docs/snippets/ts-bundle.mdx +14 -0
- package/package.json +1 -1
- package/src/py/agent/schema.json +1 -1
- package/src/py/fast-api/schema.json +2 -2
- package/src/py/mcp-server/schema.json +1 -1
- package/src/smithy/ts/api/schema.json +2 -2
- package/src/trpc/backend/schema.json +2 -2
- package/src/ts/agent/schema.json +1 -1
- package/src/ts/mcp-server/schema.json +1 -1
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Runtime Configuration
|
|
3
|
+
description: How runtime configuration connects your generated projects using AWS AppConfig
|
|
4
|
+
---
|
|
5
|
+
import { Tabs, TabItem, Steps } from '@astrojs/starlight/components';
|
|
6
|
+
import Infrastructure from '@components/infrastructure.astro';
|
|
7
|
+
import Link from '@components/link.astro';
|
|
8
|
+
|
|
9
|
+
Runtime configuration is the mechanism used by Nx Plugin for AWS to pass deploy-time values between generated projects and components so they can connect to one another. For example, when you generate an API, its URL is automatically registered in the runtime configuration so that a connected website can discover it.
|
|
10
|
+
|
|
11
|
+
## How It Works
|
|
12
|
+
|
|
13
|
+
Runtime configuration is organised into **namespaces**. Each namespace is a logical grouping of related configuration values. At deploy time, all namespaces are stored in **AWS AppConfig** as Configuration Profiles.
|
|
14
|
+
|
|
15
|
+
Two built-in namespaces are used by generated constructs:
|
|
16
|
+
|
|
17
|
+
- **`connection`** — configuration that enables generated projects to connect to each other:
|
|
18
|
+
- **API URLs** — registered automatically by API constructs
|
|
19
|
+
- **Cognito settings** — registered automatically by the UserIdentity construct
|
|
20
|
+
- **Agent runtime ARNs** — added by the connection generator when you connect a React website to an Agent
|
|
21
|
+
- **`agentcore`** — AgentCore runtime ARNs for agents and MCP servers. Registered automatically by the agent/MCP constructs and used for server-side discovery (agent → agent via A2A, agent → MCP server).
|
|
22
|
+
|
|
23
|
+
The `connection` namespace is also deployed as a `runtime-config.json` file to your website's S3 bucket, enabling client-side discovery of backend resources. The `agentcore` namespace is server-side only (via AppConfig) so agent runtime ARNs are not exposed to the frontend unless you explicitly connect a website to an agent.
|
|
24
|
+
|
|
25
|
+
You can define as many additional namespaces as you like, providing a convenient alternative to environment variables for passing deploy-time values such as DynamoDB table names to your Lambda functions or other compute resources.
|
|
26
|
+
|
|
27
|
+
```d2
|
|
28
|
+
direction: down
|
|
29
|
+
|
|
30
|
+
iac: "Infrastructure as code\nRuntimeConfig.set(...)"
|
|
31
|
+
|
|
32
|
+
appconfig: "AWS AppConfig" {
|
|
33
|
+
shape: cylinder
|
|
34
|
+
connection: "connection namespace"
|
|
35
|
+
agentcore: "agentcore namespace"
|
|
36
|
+
custom: "custom namespaces"
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
s3: "website S3 bucket" {
|
|
40
|
+
shape: cylinder
|
|
41
|
+
rcj: runtime-config.json {
|
|
42
|
+
shape: page
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
website: React website
|
|
47
|
+
|
|
48
|
+
server: Lambda / agent
|
|
49
|
+
|
|
50
|
+
iac -> appconfig.connection
|
|
51
|
+
iac -> appconfig.agentcore
|
|
52
|
+
iac -> appconfig.custom
|
|
53
|
+
|
|
54
|
+
appconfig.connection -> s3.rcj: deployed
|
|
55
|
+
s3.rcj -> website: fetched at load
|
|
56
|
+
|
|
57
|
+
appconfig.connection -> server
|
|
58
|
+
appconfig.agentcore -> server: Powertools getAppConfig
|
|
59
|
+
appconfig.custom -> server
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Infrastructure
|
|
63
|
+
|
|
64
|
+
### Writing Configuration
|
|
65
|
+
|
|
66
|
+
Generated constructs automatically write relevant configuration to the `connection` namespace. You can also write your own values to any namespace.
|
|
67
|
+
|
|
68
|
+
<Infrastructure>
|
|
69
|
+
<Fragment slot="cdk">
|
|
70
|
+
The `RuntimeConfig` CDK construct is a stage-scoped singleton. Use `set()` to write a key into a namespace:
|
|
71
|
+
|
|
72
|
+
```ts title="packages/infra/src/stacks/application-stack.ts"
|
|
73
|
+
import { RuntimeConfig } from ':my-scope/common-constructs';
|
|
74
|
+
|
|
75
|
+
const rc = RuntimeConfig.ensure(this);
|
|
76
|
+
|
|
77
|
+
// Built-in 'connection' namespace (written automatically by generated constructs)
|
|
78
|
+
rc.set('connection', 'apis', {
|
|
79
|
+
...rc.get('connection').apis,
|
|
80
|
+
MyApi: api.url,
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
// Custom namespaces for server-side configuration
|
|
84
|
+
rc.set('tables', 'users', {
|
|
85
|
+
tableName: usersTable.tableName,
|
|
86
|
+
tableArn: usersTable.tableArn,
|
|
87
|
+
});
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
At synth/deploy time, `RuntimeConfig` creates an **AWS AppConfig** application containing:
|
|
91
|
+
- A **Configuration Profile** for each namespace
|
|
92
|
+
- A **Hosted Configuration Version** with the JSON data for each profile
|
|
93
|
+
- An instant **Deployment** to the `default` environment
|
|
94
|
+
</Fragment>
|
|
95
|
+
<Fragment slot="terraform">
|
|
96
|
+
Terraform wires runtime configuration across three `core/runtime-config/*` modules. Declare them in the following order in your root module:
|
|
97
|
+
|
|
98
|
+
<Steps>
|
|
99
|
+
|
|
100
|
+
1. **`core/runtime-config/appconfig`** — declared once, near the top of the root module. Creates the AppConfig application, environment, deployment strategy and one configuration profile per namespace. Its `application_id` and `application_arn` outputs are passed into every module that reads runtime configuration at runtime (agents, MCP servers, Lambda functions, etc.).
|
|
101
|
+
|
|
102
|
+
```hcl title="packages/infra/src/main.tf"
|
|
103
|
+
module "runtime_config_appconfig" {
|
|
104
|
+
source = "../../common/terraform/src/core/runtime-config/appconfig"
|
|
105
|
+
|
|
106
|
+
application_name = "my-app-runtime-config"
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
2. **`core/runtime-config/entry`** — one invocation per contribution. Generated API, agent and MCP modules call this internally to publish their URLs and ARNs. Call it directly to publish custom configuration.
|
|
111
|
+
|
|
112
|
+
```hcl title="packages/infra/src/main.tf"
|
|
113
|
+
# Automatic — done inside generated modules
|
|
114
|
+
module "add_api_url" {
|
|
115
|
+
source = "../../common/terraform/src/core/runtime-config/entry"
|
|
116
|
+
|
|
117
|
+
namespace = "connection"
|
|
118
|
+
key = "apis"
|
|
119
|
+
value = { "MyApi" = module.my_api.api_url }
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
# Custom namespace for server-side configuration
|
|
123
|
+
module "add_table_config" {
|
|
124
|
+
source = "../../common/terraform/src/core/runtime-config/entry"
|
|
125
|
+
|
|
126
|
+
namespace = "tables"
|
|
127
|
+
key = "users"
|
|
128
|
+
value = {
|
|
129
|
+
tableName = aws_dynamodb_table.users.name
|
|
130
|
+
arn = aws_dynamodb_table.users.arn
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
3. **`core/runtime-config/appconfig-deployment`** — declared once, at the end of the root module, with `depends_on` covering every module that contributes an entry. Aggregates the contributed entries into one JSON per namespace and creates the hosted configuration version + deployment against the shared application.
|
|
136
|
+
|
|
137
|
+
```hcl title="packages/infra/src/main.tf"
|
|
138
|
+
module "runtime_config_appconfig_deployment" {
|
|
139
|
+
source = "../../common/terraform/src/core/runtime-config/appconfig-deployment"
|
|
140
|
+
|
|
141
|
+
application_id = module.runtime_config_appconfig.application_id
|
|
142
|
+
environment_id = module.runtime_config_appconfig.environment_id
|
|
143
|
+
deployment_strategy_id = module.runtime_config_appconfig.deployment_strategy_id
|
|
144
|
+
configuration_profile_ids = module.runtime_config_appconfig.configuration_profile_ids
|
|
145
|
+
namespaces = module.runtime_config_appconfig.namespaces
|
|
146
|
+
|
|
147
|
+
depends_on = [
|
|
148
|
+
module.my_api,
|
|
149
|
+
module.add_table_config,
|
|
150
|
+
# ...every module that contributes an entry
|
|
151
|
+
]
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
</Steps>
|
|
156
|
+
</Fragment>
|
|
157
|
+
</Infrastructure>
|
|
158
|
+
|
|
159
|
+
### Reading Configuration
|
|
160
|
+
|
|
161
|
+
Server-side consumers need the **AppConfig Application ID** and IAM permissions to read configuration at runtime. Generated constructs handle this automatically.
|
|
162
|
+
|
|
163
|
+
<Infrastructure>
|
|
164
|
+
<Fragment slot="cdk">
|
|
165
|
+
Use `appConfigApplicationId` to get the AppConfig Application ID, and `grantReadAppConfig()` to grant read permissions:
|
|
166
|
+
|
|
167
|
+
```ts title="packages/infra/src/stacks/application-stack.ts"
|
|
168
|
+
const rc = RuntimeConfig.ensure(this);
|
|
169
|
+
|
|
170
|
+
// Get the AppConfig Application ID (lazy token, resolved at synth time)
|
|
171
|
+
const appId = rc.appConfigApplicationId;
|
|
172
|
+
|
|
173
|
+
// Pass it as an environment variable to a Lambda function
|
|
174
|
+
const myFunction = new Function(this, 'MyFunction', {
|
|
175
|
+
// ...
|
|
176
|
+
environment: {
|
|
177
|
+
RUNTIME_CONFIG_APP_ID: appId,
|
|
178
|
+
},
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
// Grant the function permission to read from AppConfig
|
|
182
|
+
rc.grantReadAppConfig(myFunction);
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
:::note[Automatic Registration]
|
|
186
|
+
Generated API and agent constructs do this automatically — you only need to do this manually if you create your own Lambda functions or compute resources that need to read runtime configuration.
|
|
187
|
+
:::
|
|
188
|
+
</Fragment>
|
|
189
|
+
<Fragment slot="terraform">
|
|
190
|
+
Reference the shared `runtime_config_appconfig` module's `application_id` output to get the AppConfig Application ID, and add the appropriate IAM policy statements:
|
|
191
|
+
|
|
192
|
+
```hcl title="packages/infra/src/main.tf"
|
|
193
|
+
# Pass the AppConfig Application ID as an environment variable
|
|
194
|
+
resource "aws_lambda_function" "my_function" {
|
|
195
|
+
# ...
|
|
196
|
+
environment {
|
|
197
|
+
variables = {
|
|
198
|
+
RUNTIME_CONFIG_APP_ID = module.runtime_config_appconfig.application_id
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
# Grant the function permission to read from AppConfig
|
|
204
|
+
resource "aws_iam_policy" "appconfig_read" {
|
|
205
|
+
name = "AppConfigReadPolicy"
|
|
206
|
+
policy = jsonencode({
|
|
207
|
+
Version = "2012-10-17"
|
|
208
|
+
Statement = [{
|
|
209
|
+
Effect = "Allow"
|
|
210
|
+
Action = [
|
|
211
|
+
"appconfig:StartConfigurationSession",
|
|
212
|
+
"appconfig:GetLatestConfiguration"
|
|
213
|
+
]
|
|
214
|
+
Resource = ["${module.runtime_config_appconfig.application_arn}/*"]
|
|
215
|
+
}]
|
|
216
|
+
})
|
|
217
|
+
}
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
:::note[Automatic Registration]
|
|
221
|
+
Generated agent and MCP modules accept `appconfig_application_id` + `appconfig_application_arn` inputs — pass the shared `runtime_config_appconfig` outputs and they wire up the environment variable and IAM permissions for you. You only need to do this manually for custom Lambda functions or compute resources.
|
|
222
|
+
:::
|
|
223
|
+
</Fragment>
|
|
224
|
+
</Infrastructure>
|
|
225
|
+
|
|
226
|
+
:::tip[Local Development]
|
|
227
|
+
If you use runtime config with custom namespaces (e.g. `tables`, `features`), you only need to define a single `RUNTIME_CONFIG_APP_ID` environment variable locally to point to your deployed AppConfig application. This allows your local APIs or agents to retrieve the same configuration as the deployed environment without needing to replicate all the individual environment variables.
|
|
228
|
+
:::
|
|
229
|
+
|
|
230
|
+
## Server-Side Access via AppConfig
|
|
231
|
+
|
|
232
|
+
Server-side consumers such as Lambda functions and agents can retrieve runtime configuration from **AWS AppConfig** using [AWS Lambda Powertools](https://docs.aws.amazon.com/powertools/).
|
|
233
|
+
|
|
234
|
+
All generated API and agent constructs are automatically configured with:
|
|
235
|
+
- The `RUNTIME_CONFIG_APP_ID` environment variable (the AppConfig Application ID)
|
|
236
|
+
- IAM permissions to read from AppConfig
|
|
237
|
+
|
|
238
|
+
<Tabs>
|
|
239
|
+
<TabItem label="TypeScript" icon="seti:typescript">
|
|
240
|
+
|
|
241
|
+
Use `getAppConfig` from [`@aws-lambda-powertools/parameters`](https://docs.aws.amazon.com/powertools/typescript/latest/features/parameters):
|
|
242
|
+
|
|
243
|
+
```ts
|
|
244
|
+
import { getAppConfig } from '@aws-lambda-powertools/parameters/appconfig';
|
|
245
|
+
|
|
246
|
+
// Retrieve the 'connection' namespace as a parsed JSON object
|
|
247
|
+
const config = await getAppConfig('connection', {
|
|
248
|
+
application: process.env.RUNTIME_CONFIG_APP_ID!,
|
|
249
|
+
environment: 'default',
|
|
250
|
+
transform: 'json',
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
// Access values
|
|
254
|
+
const apiUrl = config.apis?.MyApi;
|
|
255
|
+
const cognitoProps = config.cognitoProps;
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
You can also retrieve custom namespaces:
|
|
259
|
+
|
|
260
|
+
```ts
|
|
261
|
+
// Retrieve a custom 'tables' namespace
|
|
262
|
+
const tablesConfig = await getAppConfig('tables', {
|
|
263
|
+
application: process.env.RUNTIME_CONFIG_APP_ID!,
|
|
264
|
+
environment: 'default',
|
|
265
|
+
transform: 'json',
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
const usersTableName = tablesConfig.users?.tableName;
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
</TabItem>
|
|
272
|
+
<TabItem label="Python" icon="seti:python">
|
|
273
|
+
|
|
274
|
+
Use `get_app_config` from [`aws_lambda_powertools.utilities.parameters`](https://docs.aws.amazon.com/powertools/python/latest/utilities/parameters/):
|
|
275
|
+
|
|
276
|
+
```python
|
|
277
|
+
import os
|
|
278
|
+
from aws_lambda_powertools.utilities import parameters
|
|
279
|
+
|
|
280
|
+
# Retrieve the 'connection' namespace as a parsed JSON object
|
|
281
|
+
config = parameters.get_app_config(
|
|
282
|
+
name="connection",
|
|
283
|
+
environment="default",
|
|
284
|
+
application=os.environ["RUNTIME_CONFIG_APP_ID"],
|
|
285
|
+
transform="json",
|
|
286
|
+
)
|
|
287
|
+
|
|
288
|
+
# Access values
|
|
289
|
+
api_url = config.get("apis", {}).get("MyApi")
|
|
290
|
+
cognito_props = config.get("cognitoProps")
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
You can also retrieve custom namespaces:
|
|
294
|
+
|
|
295
|
+
```python
|
|
296
|
+
# Retrieve a custom 'tables' namespace
|
|
297
|
+
tables_config = parameters.get_app_config(
|
|
298
|
+
name="tables",
|
|
299
|
+
environment="default",
|
|
300
|
+
application=os.environ["RUNTIME_CONFIG_APP_ID"],
|
|
301
|
+
transform="json",
|
|
302
|
+
)
|
|
303
|
+
|
|
304
|
+
users_table_name = tables_config.get("users", {}).get("tableName")
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
</TabItem>
|
|
308
|
+
</Tabs>
|
|
309
|
+
|
|
310
|
+
## Client-Side Access
|
|
311
|
+
|
|
312
|
+
For websites, the `connection` namespace is deployed as a `runtime-config.json` file to the S3 bucket. See the <Link path="guides/react-website#runtime-configuration">React Website Runtime Configuration</Link> guide for details on how to access these values from your frontend code.
|
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Terraform Infrastructure
|
|
3
|
+
description: Reference documentation for Terraform Infrastructure
|
|
4
|
+
generator: terraform#project
|
|
5
|
+
---
|
|
6
|
+
import { FileTree, Tabs, TabItem } from '@astrojs/starlight/components';
|
|
7
|
+
import RunGenerator from '@components/run-generator.astro';
|
|
8
|
+
import Link from '@components/link.astro';
|
|
9
|
+
import GeneratorParameters from '@components/generator-parameters.astro';
|
|
10
|
+
import NxCommands from '@components/nx-commands.astro';
|
|
11
|
+
import OptionFilter from '@components/option-filter.astro';
|
|
12
|
+
|
|
13
|
+
[Terraform](https://www.terraform.io/) is an open-source infrastructure as code software tool that enables you to safely and predictably create, change, and improve infrastructure.
|
|
14
|
+
|
|
15
|
+
The Terraform infrastructure generator creates a Terraform infrastructure project. The generated application includes security best practices through [Checkov](https://www.checkov.io/) security checks.
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
### Generate a Terraform Project
|
|
20
|
+
|
|
21
|
+
You can generate a new Terraform project in two ways:
|
|
22
|
+
|
|
23
|
+
<RunGenerator generator="terraform#project" requiredParameters={{ name: 'tf-infra' }} />
|
|
24
|
+
|
|
25
|
+
### Options
|
|
26
|
+
|
|
27
|
+
<GeneratorParameters generator="terraform#project" />
|
|
28
|
+
|
|
29
|
+
## Generator Output
|
|
30
|
+
|
|
31
|
+
The generator creates different file structures depending on the project type:
|
|
32
|
+
|
|
33
|
+
<OptionFilter when={{ type: 'application' }} description="Application type: full Terraform app with remote state management">
|
|
34
|
+
### Application Type
|
|
35
|
+
|
|
36
|
+
For application projects (`--type=application`), the generator creates a complete Terraform application with remote state management:
|
|
37
|
+
|
|
38
|
+
<FileTree>
|
|
39
|
+
|
|
40
|
+
- src
|
|
41
|
+
- main.tf Main Terraform configuration file
|
|
42
|
+
- providers.tf Provider configuration with S3 backend
|
|
43
|
+
- variables.tf Input variable definitions
|
|
44
|
+
- outputs.tf Output value definitions
|
|
45
|
+
- env Environment-specific variable files
|
|
46
|
+
- dev.tfvars Development environment variables
|
|
47
|
+
- bootstrap Bootstrap configuration for remote state
|
|
48
|
+
- main.tf S3 bucket and policies for state storage
|
|
49
|
+
- providers.tf AWS provider configuration
|
|
50
|
+
- variables.tf Bootstrap variable definitions
|
|
51
|
+
- scripts Node helpers run by the nx `bootstrap` and `init` targets
|
|
52
|
+
- aws-config.ts Resolves account + region via the AWS SDK credential chain
|
|
53
|
+
- bootstrap.ts Pulls/pushes the bootstrap tfstate and runs `terraform apply`
|
|
54
|
+
- init.ts Runs `terraform init` with the S3 backend config
|
|
55
|
+
- project.json Project configuration and build targets
|
|
56
|
+
|
|
57
|
+
</FileTree>
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
:::note[Shared Terraform Modules]
|
|
61
|
+
The generator also creates a `packages/common/terraform` library which initially just adds a metrics module (creates an empty Cloudformation stack with metadata) that is automatically instrumented so that the `nx-plugin-for-aws` team can track usage metrics.
|
|
62
|
+
:::
|
|
63
|
+
</OptionFilter>
|
|
64
|
+
|
|
65
|
+
<OptionFilter when={{ type: 'library' }} description="Library type: simpler layout for reusable Terraform modules">
|
|
66
|
+
### Library Type
|
|
67
|
+
|
|
68
|
+
For library projects (`--type=library`), the generator creates a simpler structure for reusable Terraform modules:
|
|
69
|
+
|
|
70
|
+
<FileTree>
|
|
71
|
+
|
|
72
|
+
- src
|
|
73
|
+
- main.tf Main Terraform module file
|
|
74
|
+
- project.json Project configuration and build targets
|
|
75
|
+
|
|
76
|
+
</FileTree>
|
|
77
|
+
</OptionFilter>
|
|
78
|
+
|
|
79
|
+
:::tip[Application vs Library]
|
|
80
|
+
Application projects include full deployment capabilities with remote state management, while library projects are designed for creating reusable Terraform modules that can be consumed by other projects.
|
|
81
|
+
:::
|
|
82
|
+
|
|
83
|
+
## Implementing your Terraform Infrastructure
|
|
84
|
+
|
|
85
|
+
You can start writing your Terraform infrastructure inside `src/main.tf`, for example:
|
|
86
|
+
|
|
87
|
+
```diff title="src/main.tf" {2-4}
|
|
88
|
+
-locals {
|
|
89
|
+
- account_id = data.aws_caller_identity.current.account_id
|
|
90
|
+
- aws_region = data.aws_region.current.id
|
|
91
|
+
-}
|
|
92
|
+
-
|
|
93
|
+
-resource "null_resource" "print_info" {
|
|
94
|
+
- # triggers = {
|
|
95
|
+
- # always_run = timestamp()
|
|
96
|
+
- # }
|
|
97
|
+
-
|
|
98
|
+
- provisioner "local-exec" {
|
|
99
|
+
- command = "echo 'AWS Region: ${local.aws_region}, AWS Account: ${local.account_id}, Environment: ${var.environment}'"
|
|
100
|
+
- }
|
|
101
|
+
-}
|
|
102
|
+
+
|
|
103
|
+
+# Declare your infrastructure here
|
|
104
|
+
+resource "aws_s3_bucket" "my_bucket" {
|
|
105
|
+
+ bucket = "my-unique-bucket-name"
|
|
106
|
+
+}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Cross project dependencies
|
|
110
|
+
|
|
111
|
+
If you wanted to execute a module from a seperate project (lib), you could do so as follows:
|
|
112
|
+
|
|
113
|
+
```
|
|
114
|
+
module "lib_module" {
|
|
115
|
+
source = "../../path/to/my-lib/src"
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
This will automatically update the Nx graph to add a dependency between your consuming application and your lib.
|
|
120
|
+
|
|
121
|
+
### Environment Configuration
|
|
122
|
+
|
|
123
|
+
Configure environment-specific variables in the `src/env/*.tfvars` files.
|
|
124
|
+
|
|
125
|
+
To add new environments, create a new `src/env/<environment>.tfvars` file with the environment-specific variables and add new entries for `apply, destroy, init, plan` in the `project.json` for the new env configuration. For example, let's assume we want to add a `prod` env:
|
|
126
|
+
|
|
127
|
+
<Tabs>
|
|
128
|
+
<TabItem label="src/env/prod.tfvars">
|
|
129
|
+
```hcl
|
|
130
|
+
# Production environment variables
|
|
131
|
+
environment = "prod"
|
|
132
|
+
region = "us-west-2"
|
|
133
|
+
```
|
|
134
|
+
</TabItem>
|
|
135
|
+
<TabItem label="project.json">
|
|
136
|
+
```diff
|
|
137
|
+
{
|
|
138
|
+
"targets": {
|
|
139
|
+
"apply": {
|
|
140
|
+
"executor": "nx:run-commands",
|
|
141
|
+
"defaultConfiguration": "dev",
|
|
142
|
+
"configurations": {
|
|
143
|
+
"dev": {
|
|
144
|
+
"command": "terraform apply ../../../dist/packages/infra/terraform/dev.tfplan"
|
|
145
|
+
},
|
|
146
|
+
+ "prod": {
|
|
147
|
+
+ "command": "terraform apply ../../../dist/packages/infra/terraform/prod.tfplan"
|
|
148
|
+
+ }
|
|
149
|
+
},
|
|
150
|
+
"options": {
|
|
151
|
+
"forwardAllArgs": true,
|
|
152
|
+
"cwd": "{projectRoot}/src"
|
|
153
|
+
},
|
|
154
|
+
"dependsOn": ["plan"]
|
|
155
|
+
},
|
|
156
|
+
"destroy": {
|
|
157
|
+
"executor": "nx:run-commands",
|
|
158
|
+
"defaultConfiguration": "dev",
|
|
159
|
+
"configurations": {
|
|
160
|
+
"dev": {
|
|
161
|
+
"command": "terraform destroy -var-file=env/dev.tfvars"
|
|
162
|
+
},
|
|
163
|
+
+ "prod": {
|
|
164
|
+
+ "command": "terraform destroy -var-file=env/prod.tfvars"
|
|
165
|
+
+ }
|
|
166
|
+
},
|
|
167
|
+
"options": {
|
|
168
|
+
"forwardAllArgs": true,
|
|
169
|
+
"cwd":"{projectRoot}/src"
|
|
170
|
+
},
|
|
171
|
+
"dependsOn": ["init"]
|
|
172
|
+
},
|
|
173
|
+
"init": {
|
|
174
|
+
"executor": "nx:run-commands",
|
|
175
|
+
"defaultConfiguration": "dev",
|
|
176
|
+
"configurations": {
|
|
177
|
+
"dev": {
|
|
178
|
+
"env": { "TF_ENV": "dev" }
|
|
179
|
+
},
|
|
180
|
+
+ "prod": {
|
|
181
|
+
+ "env": { "TF_ENV": "prod" }
|
|
182
|
+
+ }
|
|
183
|
+
},
|
|
184
|
+
"options": {
|
|
185
|
+
"forwardAllArgs": true,
|
|
186
|
+
"commands": ["tsx {projectRoot}/scripts/init.ts {projectRoot}"],
|
|
187
|
+
"cwd": "{workspaceRoot}"
|
|
188
|
+
}
|
|
189
|
+
},
|
|
190
|
+
"plan": {
|
|
191
|
+
"executor": "nx:run-commands",
|
|
192
|
+
"defaultConfiguration": "dev",
|
|
193
|
+
"configurations": {
|
|
194
|
+
"dev": {
|
|
195
|
+
"command": "terraform plan -var-file=env/dev.tfvars -out=../../../dist/packages/infra/terraform/dev.tfplan"
|
|
196
|
+
},
|
|
197
|
+
+ "prod": {
|
|
198
|
+
+ "command": "terraform plan -var-file=env/dev.tfvars -out=../../../dist/packages/infra/terraform/prod.tfplan"
|
|
199
|
+
+ }
|
|
200
|
+
},
|
|
201
|
+
"options": {
|
|
202
|
+
"forwardAllArgs": true,
|
|
203
|
+
"cwd": "{projectRoot}/src"
|
|
204
|
+
},
|
|
205
|
+
"dependsOn": ["init"]
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
```
|
|
210
|
+
</TabItem>
|
|
211
|
+
</Tabs>
|
|
212
|
+
|
|
213
|
+
:::tip[Default Environment]
|
|
214
|
+
By default, all targets assume `dev` environment, however you can target a specific environment as follows: <NxCommands commands={['apply tf-infra --configuration=prod']} />
|
|
215
|
+
|
|
216
|
+
You can also swap environment at any time as the state segments the tfstate automatically between environments.
|
|
217
|
+
:::
|
|
218
|
+
|
|
219
|
+
<OptionFilter when={{ type: 'application' }} description="Remote state bootstrap is application-only">
|
|
220
|
+
### Remote State Bootstrap (Application Projects Only)
|
|
221
|
+
|
|
222
|
+
Before deploying your infrastructure, you'll need to bootstrap the remote state backend. This creates an S3 bucket to store your Terraform state files:
|
|
223
|
+
|
|
224
|
+
<NxCommands commands={['bootstrap tf-infra']} />
|
|
225
|
+
|
|
226
|
+
:::note[AWS Profile Configuration]
|
|
227
|
+
Ensure your AWS CLI profile is configured to the account/region you wish to deploy the bootstrap resources into.
|
|
228
|
+
|
|
229
|
+
The bootstrap target is only available for application type projects. Library projects don't require remote state management as they are designed to be reusable modules.
|
|
230
|
+
:::
|
|
231
|
+
</OptionFilter>
|
|
232
|
+
|
|
233
|
+
## Available Targets
|
|
234
|
+
|
|
235
|
+
The available targets depend on your project type:
|
|
236
|
+
|
|
237
|
+
### Common Targets (Both Application and Library)
|
|
238
|
+
|
|
239
|
+
#### Validating your Infrastructure
|
|
240
|
+
|
|
241
|
+
You can validate your Terraform configuration using the `validate` target:
|
|
242
|
+
|
|
243
|
+
<NxCommands commands={['validate tf-infra']} />
|
|
244
|
+
|
|
245
|
+
#### Formatting your Code
|
|
246
|
+
|
|
247
|
+
Format your Terraform code using the `fmt` target:
|
|
248
|
+
|
|
249
|
+
<NxCommands commands={['fmt tf-infra']} />
|
|
250
|
+
|
|
251
|
+
#### Security Testing
|
|
252
|
+
|
|
253
|
+
Run security checks on your infrastructure using Checkov with the `test` target:
|
|
254
|
+
|
|
255
|
+
<NxCommands commands={['test tf-infra']} />
|
|
256
|
+
|
|
257
|
+
You will find your security test results in the root `dist` folder, under `dist/packages/<my-terraform-project>/checkov`.
|
|
258
|
+
|
|
259
|
+
<OptionFilter when={{ type: 'application' }} description="Application-only targets: plan / apply / destroy / etc.">
|
|
260
|
+
### Application-Only Targets
|
|
261
|
+
|
|
262
|
+
The following targets are only available for application type projects:
|
|
263
|
+
|
|
264
|
+
#### Planning your Infrastructure
|
|
265
|
+
|
|
266
|
+
Before applying changes, you can see what Terraform will do by running the `plan` target:
|
|
267
|
+
|
|
268
|
+
<NxCommands commands={['plan tf-infra']} />
|
|
269
|
+
|
|
270
|
+
This will create a plan file in `dist/packages/<my-terraform-project>/terraform/dev.tfplan`.
|
|
271
|
+
|
|
272
|
+
#### Initializing Terraform
|
|
273
|
+
|
|
274
|
+
Initialize your Terraform working directory with the `init` target:
|
|
275
|
+
|
|
276
|
+
<NxCommands commands={['run tf-infra:init']} />
|
|
277
|
+
|
|
278
|
+
#### Deploying to AWS
|
|
279
|
+
|
|
280
|
+
After planning, you can deploy your infrastructure to AWS using the `apply` target:
|
|
281
|
+
|
|
282
|
+
<NxCommands commands={['apply tf-infra']} />
|
|
283
|
+
|
|
284
|
+
:::tip[Auto-Approve]
|
|
285
|
+
The above command applies the plan created by the `plan` target. Make sure to run `plan` first to review the changes.
|
|
286
|
+
:::
|
|
287
|
+
|
|
288
|
+
:::note[Deploy Alias]
|
|
289
|
+
A `deploy` target is also available as an alias for `apply`. You can use either <NxCommands commands={['deploy tf-infra']} /> or <NxCommands commands={['apply tf-infra']} /> interchangeably.
|
|
290
|
+
:::
|
|
291
|
+
|
|
292
|
+
#### Getting Outputs
|
|
293
|
+
|
|
294
|
+
Retrieve output values from your Terraform configuration:
|
|
295
|
+
|
|
296
|
+
<NxCommands commands={['output tf-infra']} />
|
|
297
|
+
|
|
298
|
+
#### Destroying Infrastructure
|
|
299
|
+
|
|
300
|
+
When you need to tear down your infrastructure, use the `destroy` target:
|
|
301
|
+
|
|
302
|
+
<NxCommands commands={['destroy tf-infra']} />
|
|
303
|
+
|
|
304
|
+
:::caution[Destructive Operation]
|
|
305
|
+
This will permanently delete all resources managed by this Terraform configuration. Use with caution!
|
|
306
|
+
:::
|
|
307
|
+
|
|
308
|
+
#### Destroying Bootstrap Resources
|
|
309
|
+
|
|
310
|
+
To clean up the bootstrap resources (S3 bucket for state storage):
|
|
311
|
+
|
|
312
|
+
<NxCommands commands={['bootstrap-destroy tf-infra']} />
|
|
313
|
+
</OptionFilter>
|
|
314
|
+
|
|
315
|
+
## More Information
|
|
316
|
+
|
|
317
|
+
For more information about Terraform, please refer to the [Terraform Documentation](https://www.terraform.io/docs) and [AWS Provider Documentation](https://registry.terraform.io/providers/hashicorp/aws/latest/docs).
|