alchemy 0.61.0 → 0.62.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/README.md +1 -2
- package/bin/alchemy.js +1406 -1464
- package/bin/commands/init.ts +29 -2
- package/bin/services/execute-alchemy.ts +1 -2
- package/lib/alchemy.d.ts +2 -2
- package/lib/alchemy.d.ts.map +1 -1
- package/lib/alchemy.js.map +1 -1
- package/lib/aws/client-props.d.ts +149 -0
- package/lib/aws/client-props.d.ts.map +1 -0
- package/lib/aws/client-props.js +1 -0
- package/lib/aws/client-props.js.map +1 -0
- package/lib/aws/credentials.d.ts +68 -5
- package/lib/aws/credentials.d.ts.map +1 -1
- package/lib/aws/credentials.js +148 -0
- package/lib/aws/credentials.js.map +1 -1
- package/lib/aws/ec2/internet-gateway-attachment.d.ts +57 -3
- package/lib/aws/ec2/internet-gateway-attachment.d.ts.map +1 -1
- package/lib/aws/ec2/internet-gateway-attachment.js +57 -3
- package/lib/aws/ec2/internet-gateway-attachment.js.map +1 -1
- package/lib/aws/ec2/internet-gateway.d.ts +68 -40
- package/lib/aws/ec2/internet-gateway.d.ts.map +1 -1
- package/lib/aws/ec2/internet-gateway.js +68 -40
- package/lib/aws/ec2/internet-gateway.js.map +1 -1
- package/lib/aws/ec2/nat-gateway.d.ts +99 -18
- package/lib/aws/ec2/nat-gateway.d.ts.map +1 -1
- package/lib/aws/ec2/nat-gateway.js +113 -37
- package/lib/aws/ec2/nat-gateway.js.map +1 -1
- package/lib/aws/ec2/route-table-association.d.ts +1 -1
- package/lib/aws/ec2/route-table-association.js +1 -1
- package/lib/aws/ec2/route-table.d.ts +64 -1
- package/lib/aws/ec2/route-table.d.ts.map +1 -1
- package/lib/aws/ec2/route-table.js +64 -1
- package/lib/aws/ec2/route-table.js.map +1 -1
- package/lib/aws/ec2/route.d.ts +60 -1
- package/lib/aws/ec2/route.d.ts.map +1 -1
- package/lib/aws/ec2/route.js +60 -1
- package/lib/aws/ec2/route.js.map +1 -1
- package/lib/aws/ec2/security-group.d.ts +96 -3
- package/lib/aws/ec2/security-group.d.ts.map +1 -1
- package/lib/aws/ec2/security-group.js +96 -3
- package/lib/aws/ec2/security-group.js.map +1 -1
- package/lib/aws/ec2/subnet.d.ts +61 -3
- package/lib/aws/ec2/subnet.d.ts.map +1 -1
- package/lib/aws/ec2/subnet.js +61 -3
- package/lib/aws/ec2/subnet.js.map +1 -1
- package/lib/aws/ec2/utils.d.ts +10 -2
- package/lib/aws/ec2/utils.d.ts.map +1 -1
- package/lib/aws/ec2/utils.js +68 -7
- package/lib/aws/ec2/utils.js.map +1 -1
- package/lib/aws/ec2/vpc.d.ts +50 -2
- package/lib/aws/ec2/vpc.d.ts.map +1 -1
- package/lib/aws/ec2/vpc.js +50 -2
- package/lib/aws/ec2/vpc.js.map +1 -1
- package/lib/aws/index.d.ts +2 -0
- package/lib/aws/index.d.ts.map +1 -1
- package/lib/aws/index.js +2 -0
- package/lib/aws/index.js.map +1 -1
- package/lib/cloudflare/api-response.js +2 -2
- package/lib/cloudflare/api-response.js.map +1 -1
- package/lib/cloudflare/api.d.ts +19 -0
- package/lib/cloudflare/api.d.ts.map +1 -1
- package/lib/cloudflare/api.js +4 -0
- package/lib/cloudflare/api.js.map +1 -1
- package/lib/cloudflare/assets.d.ts.map +1 -1
- package/lib/cloudflare/assets.js +3 -4
- package/lib/cloudflare/assets.js.map +1 -1
- package/lib/cloudflare/bucket.d.ts +5 -3
- package/lib/cloudflare/bucket.d.ts.map +1 -1
- package/lib/cloudflare/bucket.js +22 -18
- package/lib/cloudflare/bucket.js.map +1 -1
- package/lib/cloudflare/bundle/plugin-compat-warning.js +7 -7
- package/lib/cloudflare/bundle/plugin-compat-warning.js.map +1 -1
- package/lib/cloudflare/cloudflare-env-proxy.js.map +1 -1
- package/lib/cloudflare/kv-namespace.d.ts +2 -2
- package/lib/cloudflare/kv-namespace.d.ts.map +1 -1
- package/lib/cloudflare/kv-namespace.js.map +1 -1
- package/lib/cloudflare/oauth.js +3 -3
- package/lib/cloudflare/oauth.js.map +1 -1
- package/lib/cloudflare/quick-tunnel.d.ts +1 -1
- package/lib/cloudflare/website.d.ts.map +1 -1
- package/lib/cloudflare/website.js +26 -97
- package/lib/cloudflare/website.js.map +1 -1
- package/lib/cloudflare/worker-bundle.d.ts.map +1 -1
- package/lib/cloudflare/worker-bundle.js +9 -8
- package/lib/cloudflare/worker-bundle.js.map +1 -1
- package/lib/cloudflare/worker-tail.d.ts.map +1 -1
- package/lib/cloudflare/worker-tail.js +6 -6
- package/lib/cloudflare/worker-tail.js.map +1 -1
- package/lib/resource.d.ts +1 -0
- package/lib/resource.d.ts.map +1 -1
- package/lib/resource.js +13 -2
- package/lib/resource.js.map +1 -1
- package/lib/scope.d.ts +24 -23
- package/lib/scope.d.ts.map +1 -1
- package/lib/scope.js +25 -20
- package/lib/scope.js.map +1 -1
- package/lib/state/cloudflare-state-store.d.ts.map +1 -1
- package/lib/state/cloudflare-state-store.js +2 -1
- package/lib/state/cloudflare-state-store.js.map +1 -1
- package/lib/util/idempotent-spawn.d.ts +10 -8
- package/lib/util/idempotent-spawn.d.ts.map +1 -1
- package/lib/util/idempotent-spawn.js +97 -78
- package/lib/util/idempotent-spawn.js.map +1 -1
- package/lib/util/index.d.ts +2 -0
- package/lib/util/index.d.ts.map +1 -0
- package/lib/util/index.js +2 -0
- package/lib/util/index.js.map +1 -0
- package/lib/util/safe-fetch.d.ts +24 -0
- package/lib/util/safe-fetch.d.ts.map +1 -1
- package/lib/util/safe-fetch.js +72 -0
- package/lib/util/safe-fetch.js.map +1 -1
- package/package.json +8 -5
- package/src/alchemy.ts +2 -2
- package/src/aws/client-props.ts +156 -0
- package/src/aws/credentials.ts +165 -4
- package/src/aws/ec2/internet-gateway-attachment.ts +59 -4
- package/src/aws/ec2/internet-gateway.ts +70 -41
- package/src/aws/ec2/nat-gateway.ts +123 -33
- package/src/aws/ec2/route-table-association.ts +1 -1
- package/src/aws/ec2/route-table.ts +66 -2
- package/src/aws/ec2/route.ts +62 -2
- package/src/aws/ec2/security-group.ts +98 -4
- package/src/aws/ec2/subnet.ts +63 -4
- package/src/aws/ec2/utils.ts +73 -7
- package/src/aws/ec2/vpc.ts +52 -3
- package/src/aws/index.ts +2 -0
- package/src/cloudflare/api-response.ts +2 -2
- package/src/cloudflare/api.ts +23 -0
- package/src/cloudflare/assets.ts +3 -4
- package/src/cloudflare/bucket.ts +27 -25
- package/src/cloudflare/bundle/plugin-compat-warning.ts +7 -7
- package/src/cloudflare/cloudflare-env-proxy.ts +2 -2
- package/src/cloudflare/kv-namespace.ts +26 -27
- package/src/cloudflare/oauth.ts +3 -3
- package/src/cloudflare/website.ts +30 -111
- package/src/cloudflare/worker-bundle.ts +9 -8
- package/src/cloudflare/worker-tail.ts +6 -8
- package/src/resource.ts +19 -2
- package/src/scope.ts +73 -43
- package/src/state/cloudflare-state-store.ts +2 -1
- package/src/util/idempotent-spawn.ts +117 -100
- package/src/util/index.ts +1 -0
- package/src/util/safe-fetch.ts +114 -0
package/src/aws/credentials.ts
CHANGED
|
@@ -1,6 +1,167 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { alchemy } from "../alchemy.ts";
|
|
2
|
+
import { isSecret } from "../secret.ts";
|
|
3
|
+
import type { AwsClientProps } from "./client-props.ts";
|
|
2
4
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
5
|
+
/**
|
|
6
|
+
* Validate AWS client properties to ensure they are strings.
|
|
7
|
+
* This follows the same pattern as Cloudflare credential validation.
|
|
8
|
+
*/
|
|
9
|
+
function validateAwsClientProps(props: AwsClientProps, context: string): void {
|
|
10
|
+
const validKeys = [
|
|
11
|
+
"accessKeyId",
|
|
12
|
+
"secretAccessKey",
|
|
13
|
+
"sessionToken",
|
|
14
|
+
"region",
|
|
15
|
+
"profile",
|
|
16
|
+
"roleArn",
|
|
17
|
+
"externalId",
|
|
18
|
+
"roleSessionName",
|
|
19
|
+
];
|
|
20
|
+
|
|
21
|
+
for (const [key, value] of Object.entries(props)) {
|
|
22
|
+
if (!validKeys.includes(key)) {
|
|
23
|
+
continue; // Ignore unknown properties
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (value !== undefined && typeof value !== "string" && !isSecret(value)) {
|
|
27
|
+
throw new Error(
|
|
28
|
+
`Invalid AWS configuration in ${context}: Property '${key}' must be a string or Secret, got ${typeof value}. ` +
|
|
29
|
+
"Please ensure all AWS credential properties are strings or Secret objects.",
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Get global AWS configuration from environment variables.
|
|
37
|
+
* This provides the base layer of AWS credential configuration.
|
|
38
|
+
*/
|
|
39
|
+
export function getGlobalAwsConfig(): AwsClientProps {
|
|
40
|
+
return {
|
|
41
|
+
accessKeyId: process.env.AWS_ACCESS_KEY_ID
|
|
42
|
+
? alchemy.secret(process.env.AWS_ACCESS_KEY_ID)
|
|
43
|
+
: undefined,
|
|
44
|
+
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY
|
|
45
|
+
? alchemy.secret(process.env.AWS_SECRET_ACCESS_KEY)
|
|
46
|
+
: undefined,
|
|
47
|
+
sessionToken: process.env.AWS_SESSION_TOKEN
|
|
48
|
+
? alchemy.secret(process.env.AWS_SESSION_TOKEN)
|
|
49
|
+
: undefined,
|
|
50
|
+
region: process.env.AWS_REGION || process.env.AWS_DEFAULT_REGION,
|
|
51
|
+
profile: process.env.AWS_PROFILE,
|
|
52
|
+
roleArn: process.env.AWS_ROLE_ARN,
|
|
53
|
+
externalId: process.env.AWS_EXTERNAL_ID,
|
|
54
|
+
roleSessionName: process.env.AWS_ROLE_SESSION_NAME,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Resolve AWS credentials using three-tier resolution: global → scope → resource.
|
|
60
|
+
*
|
|
61
|
+
* This function implements a comprehensive credential resolution system that allows
|
|
62
|
+
* for flexible AWS credential management across different levels of your application.
|
|
63
|
+
* It enables multi-account and multi-region deployments by providing a consistent
|
|
64
|
+
* way to override credentials at different scopes.
|
|
65
|
+
*
|
|
66
|
+
* The resolution follows this precedence order:
|
|
67
|
+
* 1. Resource-level credentials (highest priority)
|
|
68
|
+
* 2. Scope-level credentials (medium priority)
|
|
69
|
+
* 3. Global environment variables (lowest priority)
|
|
70
|
+
*
|
|
71
|
+
* Supported credential properties include:
|
|
72
|
+
* - `region`: AWS region (e.g., 'us-west-2', 'eu-central-1')
|
|
73
|
+
* - `profile`: AWS profile name from credentials file
|
|
74
|
+
* - `accessKeyId`: AWS access key ID
|
|
75
|
+
* - `secretAccessKey`: AWS secret access key
|
|
76
|
+
* - `sessionToken`: AWS session token for temporary credentials
|
|
77
|
+
* - `roleArn`: AWS role ARN to assume
|
|
78
|
+
* - `roleSessionName`: Session name when assuming a role
|
|
79
|
+
* - `externalId`: External ID when assuming a role
|
|
80
|
+
*
|
|
81
|
+
* @param resourceProps - Resource-level AWS credential properties (optional)
|
|
82
|
+
* @returns Resolved AWS client properties with validation
|
|
83
|
+
*
|
|
84
|
+
* @throws {Error} When scope contains invalid AWS configuration
|
|
85
|
+
* @throws {Error} When resource properties contain invalid AWS configuration
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* ```typescript
|
|
89
|
+
* // Basic usage with resource-level credentials
|
|
90
|
+
* const credentials = resolveAwsCredentials({
|
|
91
|
+
* region: "us-west-2",
|
|
92
|
+
* profile: "production"
|
|
93
|
+
* });
|
|
94
|
+
* ```
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* ```typescript
|
|
98
|
+
* // Usage with scope-level credentials
|
|
99
|
+
* await alchemy.run("my-app", {
|
|
100
|
+
* aws: {
|
|
101
|
+
* region: "eu-west-1",
|
|
102
|
+
* profile: "staging"
|
|
103
|
+
* }
|
|
104
|
+
* }, async () => {
|
|
105
|
+
* // Resources created here will use the scope credentials by default
|
|
106
|
+
* const vpc = await Vpc("main-vpc", {
|
|
107
|
+
* cidrBlock: "10.0.0.0/16"
|
|
108
|
+
* });
|
|
109
|
+
*
|
|
110
|
+
* // Resources can override scope credentials
|
|
111
|
+
* const crossRegionSubnet = await Subnet("cross-region-subnet", {
|
|
112
|
+
* vpc,
|
|
113
|
+
* cidrBlock: "10.0.1.0/24",
|
|
114
|
+
* region: "us-east-1" // Override scope region
|
|
115
|
+
* });
|
|
116
|
+
* });
|
|
117
|
+
* ```
|
|
118
|
+
*/
|
|
119
|
+
export async function resolveAwsCredentials(
|
|
120
|
+
resourceProps?: AwsClientProps,
|
|
121
|
+
): Promise<AwsClientProps> {
|
|
122
|
+
// 1. Start with global environment variables (lowest priority)
|
|
123
|
+
const globalConfig = getGlobalAwsConfig();
|
|
124
|
+
|
|
125
|
+
// 2. Layer in scope-level credentials (medium priority)
|
|
126
|
+
let scopeConfig: AwsClientProps = {};
|
|
127
|
+
try {
|
|
128
|
+
// Import Scope dynamically to avoid circular dependency
|
|
129
|
+
const { Scope } = await import("../scope.ts");
|
|
130
|
+
const currentScope = Scope.getScope();
|
|
131
|
+
if (currentScope?.providerCredentials?.aws) {
|
|
132
|
+
scopeConfig = currentScope.providerCredentials.aws;
|
|
133
|
+
|
|
134
|
+
// Validate scope-level credentials if provided
|
|
135
|
+
validateAwsClientProps(scopeConfig, "scope");
|
|
136
|
+
}
|
|
137
|
+
} catch (error) {
|
|
138
|
+
// If we can't access scope (e.g., not running in scope context), just continue
|
|
139
|
+
// with empty scope config unless it's a validation error
|
|
140
|
+
if (
|
|
141
|
+
error instanceof Error &&
|
|
142
|
+
error.message.includes("Invalid AWS configuration")
|
|
143
|
+
) {
|
|
144
|
+
throw error;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// 3. Layer in resource-level credentials (highest priority)
|
|
149
|
+
const resourceConfig = resourceProps || {};
|
|
150
|
+
|
|
151
|
+
// Validate resource-level credentials if provided
|
|
152
|
+
if (resourceProps && Object.keys(resourceProps).length > 0) {
|
|
153
|
+
validateAwsClientProps(resourceProps, "resource properties");
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// Merge configurations with proper precedence (later properties override earlier ones)
|
|
157
|
+
const resolvedConfig = {
|
|
158
|
+
...globalConfig,
|
|
159
|
+
...scopeConfig,
|
|
160
|
+
...resourceConfig,
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
// Filter out undefined values from the final result
|
|
164
|
+
return Object.fromEntries(
|
|
165
|
+
Object.entries(resolvedConfig).filter(([_, value]) => value !== undefined),
|
|
166
|
+
) as AwsClientProps;
|
|
6
167
|
}
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
type TimeoutConfig,
|
|
9
9
|
waitForResourceState,
|
|
10
10
|
} from "../../util/timeout.ts";
|
|
11
|
+
import type { AwsClientProps } from "../client-props.ts";
|
|
11
12
|
import type { InternetGateway } from "./internet-gateway.ts";
|
|
12
13
|
import { callEC2Api, createEC2Client } from "./utils.ts";
|
|
13
14
|
import type { Vpc } from "./vpc.ts";
|
|
@@ -15,7 +16,7 @@ import type { Vpc } from "./vpc.ts";
|
|
|
15
16
|
/**
|
|
16
17
|
* Properties for creating or updating an Internet Gateway Attachment
|
|
17
18
|
*/
|
|
18
|
-
export interface InternetGatewayAttachmentProps {
|
|
19
|
+
export interface InternetGatewayAttachmentProps extends AwsClientProps {
|
|
19
20
|
/**
|
|
20
21
|
* The Internet Gateway to attach
|
|
21
22
|
*/
|
|
@@ -67,6 +68,9 @@ export interface InternetGatewayAttachment
|
|
|
67
68
|
* allowing traffic to flow between the VPC and the internet when combined with proper
|
|
68
69
|
* routing configuration.
|
|
69
70
|
*
|
|
71
|
+
* Supports AWS credential overrides at the resource level, allowing you to deploy Internet Gateway Attachments
|
|
72
|
+
* to different AWS accounts or regions than the default scope configuration.
|
|
73
|
+
*
|
|
70
74
|
* @example
|
|
71
75
|
* // Basic Internet Gateway attachment for internet connectivity
|
|
72
76
|
* const vpc = await Vpc("main-vpc", {
|
|
@@ -81,6 +85,36 @@ export interface InternetGatewayAttachment
|
|
|
81
85
|
* });
|
|
82
86
|
*
|
|
83
87
|
* @example
|
|
88
|
+
* // Internet Gateway Attachment with AWS credential overrides
|
|
89
|
+
* const crossAccountAttachment = await InternetGatewayAttachment("cross-account-attachment", {
|
|
90
|
+
* internetGateway: igw,
|
|
91
|
+
* vpc: vpc,
|
|
92
|
+
* // Override AWS credentials for this specific resource
|
|
93
|
+
* region: "us-east-1",
|
|
94
|
+
* profile: "production-account",
|
|
95
|
+
* });
|
|
96
|
+
*
|
|
97
|
+
* @example
|
|
98
|
+
* // Internet Gateway Attachment in different region with role assumption
|
|
99
|
+
* const multiRegionAttachment = await InternetGatewayAttachment("multi-region-attachment", {
|
|
100
|
+
* internetGateway: euIgw,
|
|
101
|
+
* vpc: euVpc,
|
|
102
|
+
* region: "eu-west-1",
|
|
103
|
+
* roleArn: "arn:aws:iam::123456789012:role/CrossRegionRole",
|
|
104
|
+
* roleSessionName: "igw-attachment-deployment",
|
|
105
|
+
* });
|
|
106
|
+
*
|
|
107
|
+
* @example
|
|
108
|
+
* // Internet Gateway Attachment with explicit credentials
|
|
109
|
+
* const explicitCredsAttachment = await InternetGatewayAttachment("explicit-creds-attachment", {
|
|
110
|
+
* internetGateway: testIgw,
|
|
111
|
+
* vpc: testVpc,
|
|
112
|
+
* accessKeyId: alchemy.secret("AKIAIOSFODNN7EXAMPLE"),
|
|
113
|
+
* secretAccessKey: alchemy.secret("wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"),
|
|
114
|
+
* region: "us-west-2",
|
|
115
|
+
* });
|
|
116
|
+
*
|
|
117
|
+
* @example
|
|
84
118
|
* // Internet Gateway attachment with custom timeout configuration
|
|
85
119
|
* // for environments with slower AWS API responses
|
|
86
120
|
* const attachment = await InternetGatewayAttachment("slow-env-attachment", {
|
|
@@ -109,7 +143,7 @@ export interface InternetGatewayAttachment
|
|
|
109
143
|
*
|
|
110
144
|
* // Create public subnet and route table for internet access
|
|
111
145
|
* const publicSubnet = await Subnet("public-subnet", {
|
|
112
|
-
* vpc,
|
|
146
|
+
* vpc: vpc,
|
|
113
147
|
* cidrBlock: "10.0.1.0/24",
|
|
114
148
|
* availabilityZone: "us-east-1a"
|
|
115
149
|
* });
|
|
@@ -121,7 +155,27 @@ export interface InternetGatewayAttachment
|
|
|
121
155
|
* const internetRoute = await Route("internet-route", {
|
|
122
156
|
* routeTable: publicRouteTable,
|
|
123
157
|
* destinationCidrBlock: "0.0.0.0/0",
|
|
124
|
-
*
|
|
158
|
+
* target: { internetGateway: igw }
|
|
159
|
+
* });
|
|
160
|
+
*
|
|
161
|
+
* @example
|
|
162
|
+
* // Multi-account deployment with scope-level and resource-level overrides
|
|
163
|
+
* await alchemy.run("production", {
|
|
164
|
+
* aws: { region: "us-west-2", profile: "main-account" }
|
|
165
|
+
* }, async () => {
|
|
166
|
+
* // This Internet Gateway Attachment uses scope credentials (main-account, us-west-2)
|
|
167
|
+
* const mainAttachment = await InternetGatewayAttachment("main-attachment", {
|
|
168
|
+
* internetGateway: mainIgw,
|
|
169
|
+
* vpc: mainVpc
|
|
170
|
+
* });
|
|
171
|
+
*
|
|
172
|
+
* // This Internet Gateway Attachment overrides to use different account
|
|
173
|
+
* const crossAccountAttachment = await InternetGatewayAttachment("cross-account-attachment", {
|
|
174
|
+
* internetGateway: crossIgw,
|
|
175
|
+
* vpc: crossVpc,
|
|
176
|
+
* profile: "secondary-account",
|
|
177
|
+
* region: "us-east-1", // Also override region
|
|
178
|
+
* });
|
|
125
179
|
* });
|
|
126
180
|
*/
|
|
127
181
|
export const InternetGatewayAttachment = Resource(
|
|
@@ -131,7 +185,8 @@ export const InternetGatewayAttachment = Resource(
|
|
|
131
185
|
_id: string,
|
|
132
186
|
props: InternetGatewayAttachmentProps,
|
|
133
187
|
): Promise<InternetGatewayAttachment> {
|
|
134
|
-
|
|
188
|
+
// Create EC2 client with credential resolution handled internally
|
|
189
|
+
const client = await createEC2Client(props);
|
|
135
190
|
const timeoutConfig = mergeTimeoutConfig(
|
|
136
191
|
INTERNET_GATEWAY_ATTACHMENT_TIMEOUT,
|
|
137
192
|
props.timeout,
|
|
@@ -9,12 +9,13 @@ import {
|
|
|
9
9
|
type TimeoutConfig,
|
|
10
10
|
waitForResourceState,
|
|
11
11
|
} from "../../util/timeout.ts";
|
|
12
|
+
import type { AwsClientProps } from "../client-props.ts";
|
|
12
13
|
import { callEC2Api, createEC2Client } from "./utils.ts";
|
|
13
14
|
|
|
14
15
|
/**
|
|
15
16
|
* Properties for creating or updating an Internet Gateway
|
|
16
17
|
*/
|
|
17
|
-
export interface InternetGatewayProps {
|
|
18
|
+
export interface InternetGatewayProps extends AwsClientProps {
|
|
18
19
|
/**
|
|
19
20
|
* Tags to apply to the Internet Gateway
|
|
20
21
|
*/
|
|
@@ -145,12 +146,15 @@ async function waitForInternetGatewayDeleted(
|
|
|
145
146
|
* 1. Provide a target in your VPC route tables for internet-routable traffic
|
|
146
147
|
* 2. Perform network address translation (NAT) for instances with public IPv4 addresses
|
|
147
148
|
*
|
|
149
|
+
* Supports AWS credential overrides at the resource level, allowing you to deploy Internet Gateways
|
|
150
|
+
* to different AWS accounts or regions than the default scope configuration.
|
|
151
|
+
*
|
|
148
152
|
* @example
|
|
149
153
|
* ```typescript
|
|
150
154
|
* // Create a basic Internet Gateway
|
|
151
|
-
* const igw =
|
|
155
|
+
* const igw = await InternetGateway("main-igw", {
|
|
152
156
|
* tags: {
|
|
153
|
-
* Name: "
|
|
157
|
+
* Name: "main-internet-gateway",
|
|
154
158
|
* Environment: "production"
|
|
155
159
|
* }
|
|
156
160
|
* });
|
|
@@ -158,59 +162,49 @@ async function waitForInternetGatewayDeleted(
|
|
|
158
162
|
*
|
|
159
163
|
* @example
|
|
160
164
|
* ```typescript
|
|
161
|
-
* // Create Internet Gateway with
|
|
162
|
-
* const
|
|
163
|
-
*
|
|
164
|
-
*
|
|
165
|
-
*
|
|
166
|
-
*
|
|
165
|
+
* // Create Internet Gateway with AWS credential overrides
|
|
166
|
+
* const crossAccountIgw = await InternetGateway("cross-account-igw", {
|
|
167
|
+
* // Override AWS credentials for this specific resource
|
|
168
|
+
* region: "us-east-1",
|
|
169
|
+
* profile: "production-account",
|
|
170
|
+
* tags: {
|
|
171
|
+
* Name: "cross-account-internet-gateway",
|
|
172
|
+
* Environment: "production"
|
|
167
173
|
* }
|
|
168
174
|
* });
|
|
169
175
|
* ```
|
|
170
176
|
*
|
|
171
177
|
* @example
|
|
172
178
|
* ```typescript
|
|
173
|
-
* // Create Internet Gateway
|
|
174
|
-
* const
|
|
175
|
-
*
|
|
176
|
-
*
|
|
177
|
-
*
|
|
178
|
-
* vpcId: vpc.vpcId
|
|
179
|
-
* });
|
|
180
|
-
* ```
|
|
181
|
-
*
|
|
182
|
-
* @example
|
|
183
|
-
* ```typescript
|
|
184
|
-
* // Access Internet Gateway properties
|
|
185
|
-
* const igw = new InternetGateway({ tags: { Name: "example-igw" } });
|
|
186
|
-
* logger.log(`Internet Gateway ID: ${igw.internetGatewayId}`);
|
|
187
|
-
* logger.log(`State: ${igw.state}`);
|
|
188
|
-
* ```
|
|
189
|
-
*
|
|
190
|
-
* Creates and manages Internet Gateways that provide internet access to VPCs.
|
|
191
|
-
* Note: Use InternetGatewayAttachment to attach the gateway to a VPC.
|
|
192
|
-
*
|
|
193
|
-
* @example
|
|
194
|
-
* // Create a basic Internet Gateway
|
|
195
|
-
* const igw = await InternetGateway("main-igw", {
|
|
179
|
+
* // Create Internet Gateway in different region with role assumption
|
|
180
|
+
* const multiRegionIgw = await InternetGateway("multi-region-igw", {
|
|
181
|
+
* region: "eu-west-1",
|
|
182
|
+
* roleArn: "arn:aws:iam::123456789012:role/CrossRegionRole",
|
|
183
|
+
* roleSessionName: "internet-gateway-deployment",
|
|
196
184
|
* tags: {
|
|
197
|
-
* Name: "
|
|
198
|
-
*
|
|
185
|
+
* Name: "eu-internet-gateway",
|
|
186
|
+
* Region: "europe"
|
|
199
187
|
* }
|
|
200
188
|
* });
|
|
189
|
+
* ```
|
|
201
190
|
*
|
|
202
191
|
* @example
|
|
203
|
-
*
|
|
204
|
-
*
|
|
192
|
+
* ```typescript
|
|
193
|
+
* // Create Internet Gateway with explicit credentials
|
|
194
|
+
* const explicitCredsIgw = await InternetGateway("explicit-creds-igw", {
|
|
195
|
+
* accessKeyId: alchemy.secret("AKIAIOSFODNN7EXAMPLE"),
|
|
196
|
+
* secretAccessKey: alchemy.secret("wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"),
|
|
197
|
+
* region: "us-west-2",
|
|
205
198
|
* tags: {
|
|
206
|
-
* Name: "
|
|
207
|
-
*
|
|
208
|
-
* Team: "backend"
|
|
199
|
+
* Name: "explicit-credentials-igw",
|
|
200
|
+
* Purpose: "testing"
|
|
209
201
|
* }
|
|
210
202
|
* });
|
|
203
|
+
* ```
|
|
211
204
|
*
|
|
212
205
|
* @example
|
|
213
|
-
*
|
|
206
|
+
* ```typescript
|
|
207
|
+
* // Create Internet Gateway with custom timeout configuration
|
|
214
208
|
* const customIgw = await InternetGateway("custom-igw", {
|
|
215
209
|
* timeout: {
|
|
216
210
|
* maxAttempts: 90,
|
|
@@ -221,6 +215,40 @@ async function waitForInternetGatewayDeleted(
|
|
|
221
215
|
* Purpose: "high-availability"
|
|
222
216
|
* }
|
|
223
217
|
* });
|
|
218
|
+
* ```
|
|
219
|
+
*
|
|
220
|
+
* @example
|
|
221
|
+
* ```typescript
|
|
222
|
+
* // Create Internet Gateway and attach to VPC
|
|
223
|
+
* const vpc = await VPC("main-vpc", { cidrBlock: "10.0.0.0/16" });
|
|
224
|
+
* const igw = await InternetGateway("vpc-igw", {
|
|
225
|
+
* tags: { Name: "vpc-internet-gateway" }
|
|
226
|
+
* });
|
|
227
|
+
* const attachment = await InternetGatewayAttachment("igw-attachment", {
|
|
228
|
+
* internetGatewayId: igw.internetGatewayId,
|
|
229
|
+
* vpcId: vpc.vpcId
|
|
230
|
+
* });
|
|
231
|
+
* ```
|
|
232
|
+
*
|
|
233
|
+
* @example
|
|
234
|
+
* ```typescript
|
|
235
|
+
* // Multi-account deployment with scope-level and resource-level overrides
|
|
236
|
+
* await alchemy.run("production", {
|
|
237
|
+
* aws: { region: "us-west-2", profile: "main-account" }
|
|
238
|
+
* }, async () => {
|
|
239
|
+
* // This IGW uses scope credentials (main-account, us-west-2)
|
|
240
|
+
* const mainIgw = await InternetGateway("main-igw", {
|
|
241
|
+
* tags: { Name: "main-account-igw" }
|
|
242
|
+
* });
|
|
243
|
+
*
|
|
244
|
+
* // This IGW overrides to use different account
|
|
245
|
+
* const crossAccountIgw = await InternetGateway("cross-account-igw", {
|
|
246
|
+
* profile: "secondary-account",
|
|
247
|
+
* region: "us-east-1", // Also override region
|
|
248
|
+
* tags: { Name: "secondary-account-igw" }
|
|
249
|
+
* });
|
|
250
|
+
* });
|
|
251
|
+
* ```
|
|
224
252
|
*/
|
|
225
253
|
export const InternetGateway = Resource(
|
|
226
254
|
"aws::InternetGateway",
|
|
@@ -229,7 +257,8 @@ export const InternetGateway = Resource(
|
|
|
229
257
|
_id: string,
|
|
230
258
|
props: InternetGatewayProps,
|
|
231
259
|
): Promise<InternetGateway> {
|
|
232
|
-
|
|
260
|
+
// Create EC2 client with credential resolution handled internally
|
|
261
|
+
const client = await createEC2Client(props);
|
|
233
262
|
const timeoutConfig = mergeTimeoutConfig(
|
|
234
263
|
INTERNET_GATEWAY_TIMEOUT,
|
|
235
264
|
props.timeout,
|