@aws/nx-plugin 1.1.1 → 1.3.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 +31 -29
- package/generators.json +16 -0
- package/migrations.json +6 -1
- package/package.json +1 -1
- package/src/agentcore-harness/generator.d.ts +1 -1
- package/src/greengrass/component/common.d.ts +60 -0
- package/src/greengrass/component/common.js +191 -0
- package/src/greengrass/component/common.js.map +1 -0
- package/src/greengrass/component/dependencies.d.ts +101 -0
- package/src/greengrass/component/dependencies.js +37 -0
- package/src/greengrass/component/dependencies.js.map +1 -0
- package/src/greengrass/component/generator.d.ts +174 -0
- package/src/greengrass/component/generator.js +32 -0
- package/src/greengrass/component/generator.js.map +1 -0
- package/src/greengrass/component/metadata.d.ts +2 -0
- package/src/greengrass/component/metadata.js +14 -0
- package/src/greengrass/component/metadata.js.map +1 -0
- package/src/greengrass/component/python/__snapshots__/generator.spec.ts.snap +450 -0
- package/src/greengrass/component/python/files/component/main.py.template +60 -0
- package/src/greengrass/component/python/files/component/recipe.yaml.template +30 -0
- package/src/greengrass/component/python/files/gdk/gdk-config.json.template +13 -0
- package/src/greengrass/component/python/files/tests/test___componentSnakeCase__.py.template +37 -0
- package/src/greengrass/component/python/generator.d.ts +15 -0
- package/src/greengrass/component/python/generator.js +192 -0
- package/src/greengrass/component/python/generator.js.map +1 -0
- package/src/greengrass/component/schema.d.js +6 -0
- package/src/greengrass/component/schema.d.js.map +1 -0
- package/src/greengrass/component/schema.d.ts +18 -0
- package/src/greengrass/component/schema.json +82 -0
- package/src/greengrass/component/typescript/__snapshots__/generator.spec.ts.snap +275 -0
- package/src/greengrass/component/typescript/files/component/recipe.yaml.template +41 -0
- package/src/greengrass/component/typescript/files/entrypoint/main.ts.template +58 -0
- package/src/greengrass/component/typescript/files/gdk/gdk-config.json.template +13 -0
- package/src/greengrass/component/typescript/files/scripts/vendor-crt-addon.ts.template +115 -0
- package/src/greengrass/component/typescript/generator.d.ts +16 -0
- package/src/greengrass/component/typescript/generator.js +194 -0
- package/src/greengrass/component/typescript/generator.js.map +1 -0
- package/src/infra/app/generator.d.ts +1 -1
- package/src/init/generator.d.ts +1 -1
- package/src/internal/test-matrix/generator.js +48 -1
- package/src/internal/test-matrix/generator.js.map +1 -1
- package/src/license/dependency-check/pre-approved.js +2 -1
- package/src/license/dependency-check/pre-approved.js.map +1 -1
- package/src/migrations/latest/ts-agent-guardrails-terraform-version-retention/metadata.json +3 -0
- package/src/migrations/latest/ts-agent-guardrails-terraform-version-retention/migration.d.ts +6 -0
- package/src/migrations/latest/ts-agent-guardrails-terraform-version-retention/migration.js +118 -0
- package/src/migrations/latest/ts-agent-guardrails-terraform-version-retention/migration.js.map +1 -0
- package/src/open-api/py-client/generator.d.ts +1 -1
- package/src/preset/__snapshots__/generator.spec.ts.snap +4 -0
- package/src/preset/generator.d.ts +1 -1
- package/src/py/agent/a2a-connection/generator.d.ts +1 -1
- package/src/py/agent/gateway-connection/generator.d.ts +1 -1
- package/src/py/agent/guardrails/__snapshots__/generator.spec.ts.snap +3813 -0
- package/src/py/agent/guardrails/files/langchain/guardrail.py.template +135 -0
- package/src/py/agent/guardrails/files/strands/guardrail.py.template +93 -0
- package/src/py/agent/guardrails/generator.d.ts +10 -0
- package/src/py/agent/guardrails/generator.js +175 -0
- package/src/py/agent/guardrails/generator.js.map +1 -0
- package/src/py/agent/guardrails/runtime-check/run_checks.py +250 -0
- package/src/py/agent/guardrails/schema.d.js +6 -0
- package/src/py/agent/guardrails/schema.d.js.map +1 -0
- package/src/py/agent/guardrails/schema.d.ts +9 -0
- package/src/py/agent/guardrails/schema.json +25 -0
- package/src/py/agent/mcp-connection/generator.d.ts +1 -1
- package/src/py/agent/react-connection/generator.d.ts +1 -1
- package/src/py/fast-api/react/generator.d.ts +1 -1
- package/src/py/project/generator.js +2 -0
- package/src/py/project/generator.js.map +1 -1
- package/src/sdk/greengrass.d.ts +6 -0
- package/src/sdk/greengrass.js +6 -0
- package/src/sdk/greengrass.js.map +1 -0
- package/src/sdk/py.d.ts +2 -0
- package/src/sdk/py.js +1 -0
- package/src/sdk/py.js.map +1 -1
- package/src/smithy/project/generator.d.ts +1 -1
- package/src/smithy/react-connection/generator.d.ts +1 -1
- package/src/terraform/project/generator.d.ts +1 -1
- package/src/trpc/react/generator.d.ts +1 -1
- package/src/ts/agent/a2a-connection/generator.d.ts +1 -1
- package/src/ts/agent/gateway-connection/generator.d.ts +1 -1
- package/src/ts/agent/guardrails/__snapshots__/generator.spec.ts.snap +54 -3
- package/src/ts/agent/guardrails/generator.js +2 -1
- package/src/ts/agent/guardrails/generator.js.map +1 -1
- package/src/ts/agent/mcp-connection/generator.d.ts +1 -1
- package/src/ts/agent/react-connection/generator.d.ts +1 -1
- package/src/ts/astro-docs/generator.d.ts +1 -1
- package/src/ts/dcr-proxy/generator.d.ts +1 -1
- package/src/ts/dynamodb/generator.d.ts +1 -1
- package/src/ts/lambda-function/generator.d.ts +1 -1
- package/src/ts/lib/generator.d.ts +1 -1
- package/src/ts/nx-generator/generator.d.ts +1 -1
- package/src/ts/nx-migration/generator.d.ts +1 -1
- package/src/ts/nx-plugin/generator.d.ts +1 -1
- package/src/ts/rdb/generator.d.ts +1 -1
- package/src/ts/react-website/agui/generator.d.ts +1 -1
- package/src/utils/__snapshots__/shared-greengrass-scripts.spec.ts.snap +1279 -0
- package/src/utils/files/common/scripts/src/greengrass/build-artifact.ts.template +236 -0
- package/src/utils/files/common/scripts/src/greengrass/component-logs.ts.template +48 -0
- package/src/utils/files/common/scripts/src/greengrass/deploy-local.ts.template +497 -0
- package/src/utils/files/common/scripts/src/greengrass/recipe-utils.ts.template +356 -0
- package/src/utils/files/common/scripts/src/greengrass/zip-writer.ts.template +121 -0
- package/src/utils/files/terraform/src/core/runtime-config/read/read.tf.template +3 -3
- package/src/utils/files/terraform/src/metrics/metrics.tf.template +1 -1
- package/src/utils/greengrass/constants.d.ts +58 -0
- package/src/utils/greengrass/constants.js +63 -0
- package/src/utils/greengrass/constants.js.map +1 -0
- package/src/utils/greengrass/naming.d.ts +46 -0
- package/src/utils/greengrass/naming.js +67 -0
- package/src/utils/greengrass/naming.js.map +1 -0
- package/src/utils/greengrass/recipe.d.ts +143 -0
- package/src/utils/greengrass/recipe.js +119 -0
- package/src/utils/greengrass/recipe.js.map +1 -0
- package/src/utils/greengrass-constructs/files/cdk/app/greengrass-component/__componentDirName__.ts.template +42 -0
- package/src/utils/greengrass-constructs/files/cdk/core/greengrass/artifact-bucket.ts.template +82 -0
- package/src/utils/greengrass-constructs/files/cdk/core/greengrass/component-version.ts.template +370 -0
- package/src/utils/greengrass-constructs/files/cdk/core/greengrass/deployment.ts.template +276 -0
- package/src/utils/greengrass-constructs/files/cdk/core/greengrass/index.ts.template +5 -0
- package/src/utils/greengrass-constructs/files/cdk/core/greengrass/next-version.ts.template +119 -0
- package/src/utils/greengrass-constructs/files/cdk/core/greengrass/recipe.ts.template +90 -0
- package/src/utils/greengrass-constructs/files/next-version/__nextVersionFileName__.template +195 -0
- package/src/utils/greengrass-constructs/files/terraform/app/greengrass-component/__componentDirName__/__componentDirName__.tf.template +26 -0
- package/src/utils/greengrass-constructs/files/terraform/core/greengrass/artifact-bucket/main.tf.template +204 -0
- package/src/utils/greengrass-constructs/files/terraform/core/greengrass/component-version/main.tf.template +156 -0
- package/src/utils/greengrass-constructs/files/terraform/core/greengrass/deployment/main.tf.template +186 -0
- package/src/utils/greengrass-constructs/greengrass-constructs.d.ts +57 -0
- package/src/utils/greengrass-constructs/greengrass-constructs.js +154 -0
- package/src/utils/greengrass-constructs/greengrass-constructs.js.map +1 -0
- package/src/utils/guardrail-constructs/files/terraform/app/guardrails/__nameKebabCase__/__nameKebabCase__-guardrail.tf.template +18 -1
- package/src/utils/guardrail-constructs/guardrail-constructs.d.ts +5 -0
- package/src/utils/guardrail-constructs/guardrail-constructs.js +8 -0
- package/src/utils/guardrail-constructs/guardrail-constructs.js.map +1 -1
- package/src/utils/guardrail-constructs/guardrail-wiring.d.ts +7 -0
- package/src/utils/guardrail-constructs/guardrail-wiring.js +6 -5
- package/src/utils/guardrail-constructs/guardrail-wiring.js.map +1 -1
- package/src/utils/nx.d.ts +15 -0
- package/src/utils/nx.js +32 -0
- package/src/utils/nx.js.map +1 -1
- package/src/utils/shared-greengrass-scripts.d.ts +21 -0
- package/src/utils/shared-greengrass-scripts.js +43 -0
- package/src/utils/shared-greengrass-scripts.js.map +1 -0
- package/src/utils/test/fake-aws/fake_aws.py +205 -0
- package/src/utils/test/python-dependencies.d.ts +6 -0
- package/src/utils/test/python-dependencies.js +19 -0
- package/src/utils/test/python-dependencies.js.map +1 -1
- package/src/utils/test/warm-python-cache.js +5 -1
- package/src/utils/test/warm-python-cache.js.map +1 -1
- package/src/utils/versions.d.ts +7 -0
- package/src/utils/versions.js +7 -0
- package/src/utils/versions.js.map +1 -1
- /package/src/{ts/agent/guardrails/files/agent → utils/guardrail-constructs/files/policy}/guardrail.json.template +0 -0
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
terraform {
|
|
2
|
+
required_providers {
|
|
3
|
+
aws = {
|
|
4
|
+
source = "hashicorp/aws"
|
|
5
|
+
version = "<%- awsProviderVersion %>"
|
|
6
|
+
}
|
|
7
|
+
awscc = {
|
|
8
|
+
source = "hashicorp/awscc"
|
|
9
|
+
version = "<%- awsccProviderVersion %>"
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
variable "recipes_dir" {
|
|
15
|
+
description = "Directory holding the one resolved recipe YAML the <c>-artifact target writes (greengrass-build/recipes). Read at plan time."
|
|
16
|
+
type = string
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
variable "artifacts_dir" {
|
|
20
|
+
description = "Directory holding the <c>-artifact target's artifact tree (greengrass-build/artifacts), containing one file per manifest platform at <artifacts_dir>/<ComponentName>/<ComponentVersion>/."
|
|
21
|
+
type = string
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
variable "bucket_name" {
|
|
25
|
+
# Use the artifact-bucket module output to wait for bucket hardening.
|
|
26
|
+
description = "Name of the shared artifact bucket this version's artifact is uploaded to."
|
|
27
|
+
type = string
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
locals {
|
|
31
|
+
placeholder_prefix = "s3://BUCKET_NAME/COMPONENT_NAME/COMPONENT_VERSION/"
|
|
32
|
+
|
|
33
|
+
recipe_files = fileset(var.recipes_dir, "*.y*ml")
|
|
34
|
+
recipe_candidate = try(tolist(local.recipe_files)[0], null)
|
|
35
|
+
recipe_path = "${var.recipes_dir}/${coalesce(local.recipe_candidate, "__no_recipe_found__")}"
|
|
36
|
+
recipe = try(yamldecode(file(local.recipe_path)), {})
|
|
37
|
+
component_name = try(local.recipe.ComponentName, "")
|
|
38
|
+
component_version = try(local.recipe.ComponentVersion, "")
|
|
39
|
+
|
|
40
|
+
artifact_dir = "${var.artifacts_dir}/${local.component_name}/${local.component_version}"
|
|
41
|
+
artifact_files = try(fileset(local.artifact_dir, "*"), [])
|
|
42
|
+
artifact_basenames = sort(tolist(local.artifact_files))
|
|
43
|
+
artifact_hashes = { for f in local.artifact_basenames : f => filesha256("${local.artifact_dir}/${f}") }
|
|
44
|
+
|
|
45
|
+
# Hash the sorted artifact names and their content digests on both IaC paths.
|
|
46
|
+
sha256 = sha256(join("\n", [for f in local.artifact_basenames : "${f}:${local.artifact_hashes[f]}"]))
|
|
47
|
+
|
|
48
|
+
destination_key_prefix = "${local.component_name}/${substr(local.sha256, 0, 32)}/"
|
|
49
|
+
replacement_prefix = "s3://${var.bucket_name}/${local.destination_key_prefix}"
|
|
50
|
+
|
|
51
|
+
# Substitute only managed artifact URIs, preserving other recipe fields
|
|
52
|
+
# and manifests without artifacts.
|
|
53
|
+
substituted_manifests = [
|
|
54
|
+
for manifest in try(local.recipe.Manifests, []) : merge(manifest, [
|
|
55
|
+
for _ in range(can(manifest.Artifacts) ? 1 : 0) : {
|
|
56
|
+
Artifacts = [
|
|
57
|
+
for artifact in manifest.Artifacts : merge(artifact, {
|
|
58
|
+
Uri = (
|
|
59
|
+
startswith(artifact.Uri, local.placeholder_prefix)
|
|
60
|
+
? "${local.replacement_prefix}${substr(artifact.Uri, length(local.placeholder_prefix), -1)}"
|
|
61
|
+
: artifact.Uri
|
|
62
|
+
)
|
|
63
|
+
})
|
|
64
|
+
]
|
|
65
|
+
}
|
|
66
|
+
]...)
|
|
67
|
+
]
|
|
68
|
+
substituted_recipe = merge(local.recipe, [
|
|
69
|
+
for _ in range(can(local.recipe.Manifests) ? 1 : 0) : {
|
|
70
|
+
Manifests = local.substituted_manifests
|
|
71
|
+
}
|
|
72
|
+
]...)
|
|
73
|
+
|
|
74
|
+
substituted_basenames = distinct(flatten([
|
|
75
|
+
for manifest in try(local.recipe.Manifests, []) : [
|
|
76
|
+
for artifact in try(manifest.Artifacts, []) : substr(artifact.Uri, length(local.placeholder_prefix), -1)
|
|
77
|
+
if startswith(artifact.Uri, local.placeholder_prefix)
|
|
78
|
+
]
|
|
79
|
+
]))
|
|
80
|
+
missing_basenames = setsubtract(toset(local.substituted_basenames), toset(local.artifact_basenames))
|
|
81
|
+
unreferenced_artifacts = setsubtract(toset(local.artifact_basenames), toset(local.substituted_basenames))
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
# Validate the recipe and artifact set before uploading or publishing.
|
|
85
|
+
resource "terraform_data" "guard" {
|
|
86
|
+
lifecycle {
|
|
87
|
+
precondition {
|
|
88
|
+
condition = length(local.recipe_files) == 1
|
|
89
|
+
error_message = "Expected exactly one resolved recipe in \"${var.recipes_dir}\" - run the component's \"-artifact\" target first. Found ${length(local.recipe_files)}."
|
|
90
|
+
}
|
|
91
|
+
precondition {
|
|
92
|
+
condition = length(local.artifact_files) >= 1
|
|
93
|
+
error_message = "Expected at least one artifact for ${local.component_name}@${local.component_version} in \"${local.artifact_dir}\" - run the component's \"-artifact\" target first. Found ${length(local.artifact_files)}."
|
|
94
|
+
}
|
|
95
|
+
precondition {
|
|
96
|
+
condition = length(local.missing_basenames) == 0
|
|
97
|
+
error_message = "\"${local.recipe_path}\" references artifact(s) ${join(", ", local.missing_basenames)}, but the files built for ${local.component_name}@${local.component_version} are ${join(", ", local.artifact_basenames)}. Make each recipe artifact Uri end in one of those names."
|
|
98
|
+
}
|
|
99
|
+
precondition {
|
|
100
|
+
condition = length(local.unreferenced_artifacts) == 0
|
|
101
|
+
error_message = "The build produced artifact(s) ${join(", ", local.unreferenced_artifacts)} for ${local.component_name}@${local.component_version} that no manifest references. Add a manifest whose artifact Uri ends in each name, then bump ComponentVersion before re-applying."
|
|
102
|
+
}
|
|
103
|
+
precondition {
|
|
104
|
+
condition = can(regex("^(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)$", local.component_version))
|
|
105
|
+
error_message = "Terraform requires an explicit ComponentVersion such as 1.0.0; NEXT_PATCH, NEXT_MINOR and NEXT_MAJOR are supported only by CDK. Set ComponentVersion in recipe.yaml, rebuild the artifact, and plan again."
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
# Changed artifact content replaces object keys and deletes the outgoing objects.
|
|
111
|
+
# Retain the publishing module before staged rollouts; see the generator guide.
|
|
112
|
+
resource "aws_s3_object" "artifact" {
|
|
113
|
+
for_each = local.artifact_hashes
|
|
114
|
+
|
|
115
|
+
bucket = var.bucket_name
|
|
116
|
+
key = "${local.destination_key_prefix}${each.key}"
|
|
117
|
+
source = "${local.artifact_dir}/${each.key}"
|
|
118
|
+
source_hash = each.value
|
|
119
|
+
|
|
120
|
+
depends_on = [terraform_data.guard]
|
|
121
|
+
|
|
122
|
+
# Upload the incoming object before deleting the outgoing key.
|
|
123
|
+
lifecycle {
|
|
124
|
+
create_before_destroy = true
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
# Recipe changes replace this immutable version; a reused version with changed
|
|
129
|
+
# content fails creation before the outgoing version is deleted.
|
|
130
|
+
resource "awscc_greengrassv2_component_version" "this" {
|
|
131
|
+
# JSON encoding keeps recipe field types intact.
|
|
132
|
+
inline_recipe = jsonencode(local.substituted_recipe)
|
|
133
|
+
|
|
134
|
+
# Publish only after all artifact uploads complete.
|
|
135
|
+
depends_on = [aws_s3_object.artifact]
|
|
136
|
+
|
|
137
|
+
# Create the new version before deleting the old one. Other fleets may still
|
|
138
|
+
# need the old version and objects; see the guide before a staged rollout.
|
|
139
|
+
lifecycle {
|
|
140
|
+
create_before_destroy = true
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
output "component_name" {
|
|
145
|
+
value = local.component_name
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
output "component_version" {
|
|
149
|
+
# Consumers wait for the published version before revising a deployment.
|
|
150
|
+
value = local.component_version
|
|
151
|
+
depends_on = [awscc_greengrassv2_component_version.this]
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
output "arn" {
|
|
155
|
+
value = awscc_greengrassv2_component_version.this.arn
|
|
156
|
+
}
|
package/src/utils/greengrass-constructs/files/terraform/core/greengrass/deployment/main.tf.template
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
terraform {
|
|
2
|
+
required_providers {
|
|
3
|
+
aws = {
|
|
4
|
+
source = "hashicorp/aws"
|
|
5
|
+
version = "<%- awsProviderVersion %>"
|
|
6
|
+
}
|
|
7
|
+
awscc = {
|
|
8
|
+
source = "hashicorp/awscc"
|
|
9
|
+
version = "<%- awsccProviderVersion %>"
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
variable "thing_group_name" {
|
|
15
|
+
description = "Creates a new aws_iot_thing_group and deploys to it. Mutually exclusive with thing_name and target_arn."
|
|
16
|
+
type = string
|
|
17
|
+
default = null
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
variable "thing_name" {
|
|
21
|
+
description = "Deploys to an existing thing, imported by name (not created). Mutually exclusive with thing_group_name and target_arn."
|
|
22
|
+
type = string
|
|
23
|
+
default = null
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
variable "target_arn" {
|
|
27
|
+
description = "Deploys to an existing thing or thing group, imported by ARN (not created). Mutually exclusive with thing_group_name and thing_name."
|
|
28
|
+
type = string
|
|
29
|
+
default = null
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
variable "parent_target_arn" {
|
|
33
|
+
description = "ARN of the parent deployment, for a subdeployment onto a nested thing group."
|
|
34
|
+
type = string
|
|
35
|
+
default = null
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
variable "deployment_name" {
|
|
39
|
+
type = string
|
|
40
|
+
default = null
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
variable "components" {
|
|
44
|
+
description = "Components to deploy, keyed by ComponentName. `configuration_update.merge`, if set, must already be a JSON-encoded string (matching the awscc schema) - use jsonencode() when building this map."
|
|
45
|
+
type = map(object({
|
|
46
|
+
component_version = optional(string)
|
|
47
|
+
configuration_update = optional(object({
|
|
48
|
+
merge = optional(string)
|
|
49
|
+
reset = optional(list(string))
|
|
50
|
+
}))
|
|
51
|
+
run_with = optional(object({
|
|
52
|
+
posix_user = optional(string)
|
|
53
|
+
windows_user = optional(string)
|
|
54
|
+
system_resource_limits = optional(object({
|
|
55
|
+
cpus = optional(number)
|
|
56
|
+
memory = optional(number)
|
|
57
|
+
}))
|
|
58
|
+
}))
|
|
59
|
+
}))
|
|
60
|
+
default = {}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
variable "deployment_policies" {
|
|
64
|
+
type = object({
|
|
65
|
+
failure_handling_policy = optional(string)
|
|
66
|
+
component_update_policy = optional(object({
|
|
67
|
+
timeout_in_seconds = optional(number)
|
|
68
|
+
action = optional(string)
|
|
69
|
+
}))
|
|
70
|
+
configuration_validation_policy = optional(object({
|
|
71
|
+
timeout_in_seconds = optional(number)
|
|
72
|
+
}))
|
|
73
|
+
})
|
|
74
|
+
default = null
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
variable "iot_job_configuration" {
|
|
78
|
+
type = any
|
|
79
|
+
default = null
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
variable "tags" {
|
|
83
|
+
type = map(string)
|
|
84
|
+
default = {}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
data "aws_partition" "current" {}
|
|
88
|
+
data "aws_region" "current" {}
|
|
89
|
+
data "aws_caller_identity" "current" {}
|
|
90
|
+
|
|
91
|
+
locals {
|
|
92
|
+
target_inputs_provided = compact([
|
|
93
|
+
var.thing_group_name != null ? "thing_group_name" : "",
|
|
94
|
+
var.thing_name != null ? "thing_name" : "",
|
|
95
|
+
var.target_arn != null ? "target_arn" : "",
|
|
96
|
+
])
|
|
97
|
+
|
|
98
|
+
creating_thing_group = var.thing_group_name != null
|
|
99
|
+
|
|
100
|
+
target_arn = (
|
|
101
|
+
var.thing_group_name != null ? aws_iot_thing_group.this[0].arn :
|
|
102
|
+
var.thing_name != null ? "arn:${data.aws_partition.current.partition}:iot:${data.aws_region.current.region}:${data.aws_caller_identity.current.account_id}:thing/${var.thing_name}" :
|
|
103
|
+
var.target_arn
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
# Validate literal target ARNs against this configuration's partition,
|
|
107
|
+
# account and region.
|
|
108
|
+
target_arn_display = var.target_arn != null ? var.target_arn : ""
|
|
109
|
+
target_arn_fields = var.target_arn != null ? split(":", var.target_arn) : []
|
|
110
|
+
target_arn_parsed = length(local.target_arn_fields) > 5
|
|
111
|
+
target_arn_partition = local.target_arn_parsed ? local.target_arn_fields[1] : ""
|
|
112
|
+
target_arn_service = local.target_arn_parsed ? local.target_arn_fields[2] : ""
|
|
113
|
+
target_arn_region = local.target_arn_parsed ? local.target_arn_fields[3] : ""
|
|
114
|
+
target_arn_account = local.target_arn_parsed ? local.target_arn_fields[4] : ""
|
|
115
|
+
|
|
116
|
+
target_arn_mismatches = !local.target_arn_parsed ? [] : compact([
|
|
117
|
+
local.target_arn_service != "iot" ? "service \"${local.target_arn_service}\" is not \"iot\"" : "",
|
|
118
|
+
local.target_arn_partition != "" && local.target_arn_partition != data.aws_partition.current.partition ? "partition \"${local.target_arn_partition}\" does not match \"${data.aws_partition.current.partition}\"" : "",
|
|
119
|
+
local.target_arn_account != "" && local.target_arn_account != data.aws_caller_identity.current.account_id ? "account \"${local.target_arn_account}\" does not match \"${data.aws_caller_identity.current.account_id}\"" : "",
|
|
120
|
+
local.target_arn_region != "" && local.target_arn_region != data.aws_region.current.region ? "region \"${local.target_arn_region}\" does not match \"${data.aws_region.current.region}\"" : "",
|
|
121
|
+
])
|
|
122
|
+
|
|
123
|
+
# Allow configuration-only entries without a component version.
|
|
124
|
+
next_version_sentinel_components = [
|
|
125
|
+
for component_name, component in var.components : component_name
|
|
126
|
+
if contains(["NEXT_PATCH", "NEXT_MINOR", "NEXT_MAJOR"], component.component_version == null ? "" : component.component_version)
|
|
127
|
+
]
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
resource "terraform_data" "guard" {
|
|
131
|
+
lifecycle {
|
|
132
|
+
precondition {
|
|
133
|
+
condition = length(local.target_inputs_provided) == 1
|
|
134
|
+
error_message = "greengrass deployment requires exactly one of thing_group_name, thing_name or target_arn, got: ${length(local.target_inputs_provided) == 0 ? "(none)" : join(", ", local.target_inputs_provided)}."
|
|
135
|
+
}
|
|
136
|
+
# Validate before creating the deployment; a module dependency can defer
|
|
137
|
+
# identity reads and this check to apply.
|
|
138
|
+
precondition {
|
|
139
|
+
condition = length(local.target_arn_mismatches) == 0
|
|
140
|
+
error_message = "target_arn \"${local.target_arn_display}\" looks like it belongs to a different environment than this configuration: ${join(", ", local.target_arn_mismatches)}."
|
|
141
|
+
}
|
|
142
|
+
precondition {
|
|
143
|
+
condition = length(local.next_version_sentinel_components) == 0
|
|
144
|
+
error_message = "Component(s) ${join(", ", local.next_version_sentinel_components)} use NEXT_* version markers. Terraform requires explicit versions such as 1.0.0; automatic versioning is supported only by CDK."
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
resource "aws_iot_thing_group" "this" {
|
|
150
|
+
count = local.creating_thing_group ? 1 : 0
|
|
151
|
+
name = var.thing_group_name
|
|
152
|
+
tags = var.tags
|
|
153
|
+
|
|
154
|
+
depends_on = [terraform_data.guard]
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
# Deleting a deployment removes cloud management state; uninstall components
|
|
158
|
+
# through a deployment revision first.
|
|
159
|
+
resource "awscc_greengrassv2_deployment" "this" {
|
|
160
|
+
deployment_name = var.deployment_name
|
|
161
|
+
target_arn = local.target_arn
|
|
162
|
+
parent_target_arn = var.parent_target_arn
|
|
163
|
+
components = var.components
|
|
164
|
+
deployment_policies = var.deployment_policies
|
|
165
|
+
iot_job_configuration = var.iot_job_configuration
|
|
166
|
+
tags = var.tags
|
|
167
|
+
|
|
168
|
+
depends_on = [terraform_data.guard]
|
|
169
|
+
|
|
170
|
+
# Create the new deployment revision before deleting the superseded resource.
|
|
171
|
+
lifecycle {
|
|
172
|
+
create_before_destroy = true
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
output "target_arn" {
|
|
177
|
+
value = local.target_arn
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
output "deployment_id" {
|
|
181
|
+
value = awscc_greengrassv2_deployment.this.deployment_id
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
output "thing_group_arn" {
|
|
185
|
+
value = local.creating_thing_group ? aws_iot_thing_group.this[0].arn : null
|
|
186
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
import { type Tree } from '@nx/devkit';
|
|
6
|
+
import type { DependencyDeclaration, MustDeclare } from '../declared-dependencies.js';
|
|
7
|
+
import type { Iac } from '../iac.js';
|
|
8
|
+
import type { IacMetadata } from '../shared-constructs-constants.js';
|
|
9
|
+
/** CDK recipe parsing and the deploy-time version resolver dependencies. */
|
|
10
|
+
export declare const GREENGRASS_CONSTRUCTS_DEPENDENCIES: readonly [{
|
|
11
|
+
readonly name: "js-yaml";
|
|
12
|
+
readonly when: (m: IacMetadata) => boolean;
|
|
13
|
+
}, {
|
|
14
|
+
readonly name: "@types/js-yaml";
|
|
15
|
+
readonly dev: true;
|
|
16
|
+
readonly when: (m: IacMetadata) => boolean;
|
|
17
|
+
}, {
|
|
18
|
+
readonly name: "@aws-sdk/client-greengrassv2";
|
|
19
|
+
readonly when: (m: IacMetadata) => boolean;
|
|
20
|
+
}];
|
|
21
|
+
/**
|
|
22
|
+
* Vends the shared `GreengrassArtifactBucket` / `GreengrassComponentVersion` /
|
|
23
|
+
* `GreengrassDeployment` / recipe-reader constructs (CDK) or modules
|
|
24
|
+
* (Terraform, via the `hashicorp/awscc` provider - neither
|
|
25
|
+
* `AWS::GreengrassV2::ComponentVersion` nor `AWS::GreengrassV2::Deployment`
|
|
26
|
+
* exists in the pinned `hashicorp/aws` provider) into
|
|
27
|
+
* `common/constructs/src/core/greengrass/` or
|
|
28
|
+
* `common/terraform/src/core/greengrass/`. Existing core files are preserved
|
|
29
|
+
* on later component runs; missing files are added. Idempotent: called from
|
|
30
|
+
* every component generator run.
|
|
31
|
+
*/
|
|
32
|
+
export declare const addGreengrassCoreConstructs: <const D extends DependencyDeclaration>(tree: Tree, { iac }: {
|
|
33
|
+
iac: Iac;
|
|
34
|
+
}, declaration: D & MustDeclare<typeof GREENGRASS_CONSTRUCTS_DEPENDENCIES, D>) => Promise<void>;
|
|
35
|
+
export interface AddGreengrassComponentAppConstructOptions {
|
|
36
|
+
readonly iac: Iac;
|
|
37
|
+
readonly componentNameClassName: string;
|
|
38
|
+
readonly componentDisplayName: string;
|
|
39
|
+
readonly componentDirName: string;
|
|
40
|
+
readonly project: string;
|
|
41
|
+
/** The host project whose `<c>-artifact` target this construct reads at synth time. */
|
|
42
|
+
readonly hostProjectName: string;
|
|
43
|
+
readonly recipesDirFromRoot: string;
|
|
44
|
+
readonly artifactsDirFromRoot: string;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Vends the per-component app construct/module: a thin
|
|
48
|
+
* `GreengrassComponentVersion` wrapper pinning this component's build output
|
|
49
|
+
* paths, at `common/constructs/src/app/greengrass/<componentDirName>.ts`
|
|
50
|
+
* (CDK) or `common/terraform/src/app/greengrass-component/<componentDirName>/`
|
|
51
|
+
* (Terraform, taking the artifact bucket's name as a plain input variable so
|
|
52
|
+
* user IaC can own or import the shared artifact repository).
|
|
53
|
+
* `OverwriteStrategy.KeepExisting` either way. Registers the host project on
|
|
54
|
+
* the shared iac project's `build`/`assemble` targets so `nx run
|
|
55
|
+
* <infra>:deploy` always deploys a freshly built artifact.
|
|
56
|
+
*/
|
|
57
|
+
export declare const addGreengrassComponentAppConstruct: <const D extends DependencyDeclaration>(tree: Tree, options: AddGreengrassComponentAppConstructOptions, declaration: D & MustDeclare<typeof GREENGRASS_CONSTRUCTS_DEPENDENCIES, D>) => Promise<void>;
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/ import { generateFiles, getProjects, joinPathFragments, logger, OverwriteStrategy, updateJson } from "@nx/devkit";
|
|
5
|
+
import { addStarExport, applyGritQL, matchGritQL } from "../ast.js";
|
|
6
|
+
import { forDependencies } from "../declared-dependencies.js";
|
|
7
|
+
import { addDependenciesToPackageJson } from "../dependencies.js";
|
|
8
|
+
import { buildDefaultComponentName } from "../greengrass/naming.js";
|
|
9
|
+
import { esmVars } from "../module-format.js";
|
|
10
|
+
import { addArtifactProjectToTargets } from "../nx.js";
|
|
11
|
+
import { PACKAGES_DIR, SHARED_CONSTRUCTS_DIR, SHARED_TERRAFORM_DIR } from "../shared-constructs-constants.js";
|
|
12
|
+
import { cdkLambdaRuntimeVars, terraformProviderVersions, withVersions } from "../versions.js";
|
|
13
|
+
/** CDK recipe parsing and the deploy-time version resolver dependencies. */ export const GREENGRASS_CONSTRUCTS_DEPENDENCIES = [
|
|
14
|
+
{
|
|
15
|
+
name: 'js-yaml',
|
|
16
|
+
when: (m)=>m.iac === 'cdk'
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
name: '@types/js-yaml',
|
|
20
|
+
dev: true,
|
|
21
|
+
when: (m)=>m.iac === 'cdk'
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
name: '@aws-sdk/client-greengrassv2',
|
|
25
|
+
when: (m)=>m.iac === 'cdk'
|
|
26
|
+
}
|
|
27
|
+
];
|
|
28
|
+
const CORE_GREENGRASS_DIR = joinPathFragments(PACKAGES_DIR, SHARED_CONSTRUCTS_DIR, 'src', 'core', 'greengrass');
|
|
29
|
+
const APP_GREENGRASS_DIR = joinPathFragments(PACKAGES_DIR, SHARED_CONSTRUCTS_DIR, 'src', 'app', 'greengrass');
|
|
30
|
+
const CORE_GREENGRASS_TERRAFORM_DIR = joinPathFragments(PACKAGES_DIR, SHARED_TERRAFORM_DIR, 'src', 'core', 'greengrass');
|
|
31
|
+
const APP_GREENGRASS_COMPONENT_TERRAFORM_DIR = joinPathFragments(PACKAGES_DIR, SHARED_TERRAFORM_DIR, 'src', 'app', 'greengrass-component');
|
|
32
|
+
/** Add the awscc requirement and default configuration to existing root modules. */ const configureGreengrassTerraformProviders = async (tree)=>{
|
|
33
|
+
const roots = [
|
|
34
|
+
...getProjects(tree).values()
|
|
35
|
+
].filter((project)=>project.projectType === 'application').map((project)=>project.sourceRoot ?? joinPathFragments(project.root, 'src')).filter((root)=>tree.children(root).some((name)=>name.endsWith('.tf')));
|
|
36
|
+
if (roots.length === 0) {
|
|
37
|
+
logger.warn('Create a terraform#project application and re-run greengrass#component to configure awscc, ' + 'or declare hashicorp/awscc and provider "awscc" { region = var.aws_region } in your root module.');
|
|
38
|
+
}
|
|
39
|
+
for (const root of roots){
|
|
40
|
+
const paths = tree.children(root).filter((name)=>name.endsWith('.tf')).map((name)=>joinPathFragments(root, name));
|
|
41
|
+
const requirement = `awscc = {
|
|
42
|
+
source = "hashicorp/awscc"
|
|
43
|
+
version = "${terraformProviderVersions().awsccProviderVersion}"
|
|
44
|
+
}`;
|
|
45
|
+
let requirementPath;
|
|
46
|
+
let configured = false;
|
|
47
|
+
for (const path of paths){
|
|
48
|
+
if (await matchGritQL(tree, path, 'language hcl\n`required_providers { $_ }`')) {
|
|
49
|
+
requirementPath ??= path;
|
|
50
|
+
}
|
|
51
|
+
configured ||= await matchGritQL(tree, path, 'language hcl\n`provider "awscc" { $config }` where { $config <: not contains `alias = $_` }');
|
|
52
|
+
}
|
|
53
|
+
if (!requirementPath) {
|
|
54
|
+
requirementPath = joinPathFragments(root, 'greengrass-providers.tf');
|
|
55
|
+
if (tree.exists(requirementPath)) {
|
|
56
|
+
throw new Error(`Cannot add awscc required_providers: ${requirementPath} already exists without a terraform block. Configure awscc in the root module.`);
|
|
57
|
+
}
|
|
58
|
+
tree.write(requirementPath, `terraform {\n required_providers {\n ${requirement}\n }\n}\n`);
|
|
59
|
+
} else {
|
|
60
|
+
const filledEmptyBlock = await applyGritQL(tree, requirementPath, `language hcl\n\`required_providers {}\` => \`required_providers {\n ${requirement}\n }\``);
|
|
61
|
+
if (!filledEmptyBlock) {
|
|
62
|
+
await applyGritQL(tree, requirementPath, 'language hcl\n`required_providers { $providers }` where { ' + '$providers <: not contains `awscc = $_`, ' + `$providers += \`\n ${requirement}\` }`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
if (!configured) {
|
|
66
|
+
tree.write(requirementPath, `${tree.read(requirementPath, 'utf-8').trimEnd()}\n\nprovider "awscc" {\n region = var.aws_region\n}\n`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
/** Registers `projectName`'s artifact target on the shared iac project the caller vended into. */ const addArtifactProjectToSharedTargets = (tree, iac, projectName)=>{
|
|
71
|
+
updateJson(tree, joinPathFragments(PACKAGES_DIR, iac === 'cdk' ? SHARED_CONSTRUCTS_DIR : SHARED_TERRAFORM_DIR, 'project.json'), (config)=>{
|
|
72
|
+
addArtifactProjectToTargets(config, projectName);
|
|
73
|
+
return config;
|
|
74
|
+
});
|
|
75
|
+
};
|
|
76
|
+
/**
|
|
77
|
+
* Vends the shared `GreengrassArtifactBucket` / `GreengrassComponentVersion` /
|
|
78
|
+
* `GreengrassDeployment` / recipe-reader constructs (CDK) or modules
|
|
79
|
+
* (Terraform, via the `hashicorp/awscc` provider - neither
|
|
80
|
+
* `AWS::GreengrassV2::ComponentVersion` nor `AWS::GreengrassV2::Deployment`
|
|
81
|
+
* exists in the pinned `hashicorp/aws` provider) into
|
|
82
|
+
* `common/constructs/src/core/greengrass/` or
|
|
83
|
+
* `common/terraform/src/core/greengrass/`. Existing core files are preserved
|
|
84
|
+
* on later component runs; missing files are added. Idempotent: called from
|
|
85
|
+
* every component generator run.
|
|
86
|
+
*/ export const addGreengrassCoreConstructs = async (tree, { iac }, declaration)=>{
|
|
87
|
+
const componentName = buildDefaultComponentName(tree, 'Namespace');
|
|
88
|
+
const componentKeyPrefix = `${componentName.slice(0, componentName.lastIndexOf('.'))}.*`;
|
|
89
|
+
if (iac === 'terraform') {
|
|
90
|
+
await configureGreengrassTerraformProviders(tree);
|
|
91
|
+
generateFiles(tree, joinPathFragments(import.meta.dirname, 'files', 'terraform', 'core', 'greengrass'), CORE_GREENGRASS_TERRAFORM_DIR, {
|
|
92
|
+
...terraformProviderVersions(),
|
|
93
|
+
componentKeyPrefix
|
|
94
|
+
}, {
|
|
95
|
+
overwriteStrategy: OverwriteStrategy.KeepExisting
|
|
96
|
+
});
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
if (iac !== 'cdk') {
|
|
100
|
+
throw new Error(`Unsupported iac ${iac}`);
|
|
101
|
+
}
|
|
102
|
+
generateFiles(tree, joinPathFragments(import.meta.dirname, 'files', 'cdk', 'core', 'greengrass'), CORE_GREENGRASS_DIR, {
|
|
103
|
+
...esmVars(tree),
|
|
104
|
+
...cdkLambdaRuntimeVars(),
|
|
105
|
+
componentKeyPrefix
|
|
106
|
+
}, {
|
|
107
|
+
overwriteStrategy: OverwriteStrategy.KeepExisting
|
|
108
|
+
});
|
|
109
|
+
generateFiles(tree, joinPathFragments(import.meta.dirname, 'files', 'next-version'), joinPathFragments(CORE_GREENGRASS_DIR, 'next-version'), {
|
|
110
|
+
nextVersionFileName: 'index.js'
|
|
111
|
+
}, {
|
|
112
|
+
overwriteStrategy: OverwriteStrategy.KeepExisting
|
|
113
|
+
});
|
|
114
|
+
await addStarExport(tree, joinPathFragments(PACKAGES_DIR, SHARED_CONSTRUCTS_DIR, 'src', 'core', 'index.ts'), './greengrass/index.js');
|
|
115
|
+
addDependenciesToPackageJson(tree, withVersions(forDependencies(declaration), [
|
|
116
|
+
'js-yaml',
|
|
117
|
+
'@aws-sdk/client-greengrassv2'
|
|
118
|
+
]), withVersions(forDependencies(declaration), [
|
|
119
|
+
'@types/js-yaml'
|
|
120
|
+
]), joinPathFragments(PACKAGES_DIR, SHARED_CONSTRUCTS_DIR, 'package.json'));
|
|
121
|
+
};
|
|
122
|
+
/**
|
|
123
|
+
* Vends the per-component app construct/module: a thin
|
|
124
|
+
* `GreengrassComponentVersion` wrapper pinning this component's build output
|
|
125
|
+
* paths, at `common/constructs/src/app/greengrass/<componentDirName>.ts`
|
|
126
|
+
* (CDK) or `common/terraform/src/app/greengrass-component/<componentDirName>/`
|
|
127
|
+
* (Terraform, taking the artifact bucket's name as a plain input variable so
|
|
128
|
+
* user IaC can own or import the shared artifact repository).
|
|
129
|
+
* `OverwriteStrategy.KeepExisting` either way. Registers the host project on
|
|
130
|
+
* the shared iac project's `build`/`assemble` targets so `nx run
|
|
131
|
+
* <infra>:deploy` always deploys a freshly built artifact.
|
|
132
|
+
*/ export const addGreengrassComponentAppConstruct = async (tree, options, declaration)=>{
|
|
133
|
+
await addGreengrassCoreConstructs(tree, {
|
|
134
|
+
iac: options.iac
|
|
135
|
+
}, forDependencies(declaration));
|
|
136
|
+
if (options.iac === 'terraform') {
|
|
137
|
+
generateFiles(tree, joinPathFragments(import.meta.dirname, 'files', 'terraform', 'app', 'greengrass-component'), APP_GREENGRASS_COMPONENT_TERRAFORM_DIR, options, {
|
|
138
|
+
overwriteStrategy: OverwriteStrategy.KeepExisting
|
|
139
|
+
});
|
|
140
|
+
addArtifactProjectToSharedTargets(tree, 'terraform', options.hostProjectName);
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
generateFiles(tree, joinPathFragments(import.meta.dirname, 'files', 'cdk', 'app', 'greengrass-component'), APP_GREENGRASS_DIR, {
|
|
144
|
+
...options,
|
|
145
|
+
...esmVars(tree)
|
|
146
|
+
}, {
|
|
147
|
+
overwriteStrategy: OverwriteStrategy.KeepExisting
|
|
148
|
+
});
|
|
149
|
+
await addStarExport(tree, joinPathFragments(APP_GREENGRASS_DIR, 'index.ts'), `./${options.componentDirName}.js`);
|
|
150
|
+
await addStarExport(tree, joinPathFragments(PACKAGES_DIR, SHARED_CONSTRUCTS_DIR, 'src', 'app', 'index.ts'), './greengrass/index.js');
|
|
151
|
+
addArtifactProjectToSharedTargets(tree, 'cdk', options.hostProjectName);
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
//# sourceMappingURL=greengrass-constructs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../packages/nx-plugin/src/utils/greengrass-constructs/greengrass-constructs.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n generateFiles,\n getProjects,\n joinPathFragments,\n logger,\n OverwriteStrategy,\n type ProjectConfiguration,\n type Tree,\n updateJson,\n} from '@nx/devkit';\nimport { addStarExport, applyGritQL, matchGritQL } from '../ast.js';\nimport type {\n DependencyDeclaration,\n MustDeclare,\n} from '../declared-dependencies.js';\nimport { forDependencies } from '../declared-dependencies.js';\nimport { addDependenciesToPackageJson } from '../dependencies.js';\nimport { buildDefaultComponentName } from '../greengrass/naming.js';\nimport type { Iac } from '../iac.js';\nimport { esmVars } from '../module-format.js';\nimport { addArtifactProjectToTargets } from '../nx.js';\nimport type { IacMetadata } from '../shared-constructs-constants.js';\nimport {\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n SHARED_TERRAFORM_DIR,\n} from '../shared-constructs-constants.js';\nimport {\n cdkLambdaRuntimeVars,\n type ITsDepVersion,\n terraformProviderVersions,\n withVersions,\n} from '../versions.js';\n\n/** CDK recipe parsing and the deploy-time version resolver dependencies. */\nexport const GREENGRASS_CONSTRUCTS_DEPENDENCIES = [\n { name: 'js-yaml', when: (m: IacMetadata) => m.iac === 'cdk' },\n {\n name: '@types/js-yaml',\n dev: true,\n when: (m: IacMetadata) => m.iac === 'cdk',\n },\n {\n name: '@aws-sdk/client-greengrassv2',\n when: (m: IacMetadata) => m.iac === 'cdk',\n },\n] as const satisfies readonly {\n name: ITsDepVersion;\n dev?: boolean;\n root?: boolean;\n when?: (m: IacMetadata) => boolean;\n}[];\n\nconst CORE_GREENGRASS_DIR = joinPathFragments(\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n 'src',\n 'core',\n 'greengrass',\n);\nconst APP_GREENGRASS_DIR = joinPathFragments(\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n 'src',\n 'app',\n 'greengrass',\n);\nconst CORE_GREENGRASS_TERRAFORM_DIR = joinPathFragments(\n PACKAGES_DIR,\n SHARED_TERRAFORM_DIR,\n 'src',\n 'core',\n 'greengrass',\n);\nconst APP_GREENGRASS_COMPONENT_TERRAFORM_DIR = joinPathFragments(\n PACKAGES_DIR,\n SHARED_TERRAFORM_DIR,\n 'src',\n 'app',\n 'greengrass-component',\n);\n/** Add the awscc requirement and default configuration to existing root modules. */\nconst configureGreengrassTerraformProviders = async (\n tree: Tree,\n): Promise<void> => {\n const roots = [...getProjects(tree).values()]\n .filter((project) => project.projectType === 'application')\n .map(\n (project) => project.sourceRoot ?? joinPathFragments(project.root, 'src'),\n )\n .filter((root) => tree.children(root).some((name) => name.endsWith('.tf')));\n if (roots.length === 0) {\n logger.warn(\n 'Create a terraform#project application and re-run greengrass#component to configure awscc, ' +\n 'or declare hashicorp/awscc and provider \"awscc\" { region = var.aws_region } in your root module.',\n );\n }\n for (const root of roots) {\n const paths = tree\n .children(root)\n .filter((name) => name.endsWith('.tf'))\n .map((name) => joinPathFragments(root, name));\n const requirement = `awscc = {\n source = \"hashicorp/awscc\"\n version = \"${terraformProviderVersions().awsccProviderVersion}\"\n }`;\n let requirementPath: string | undefined;\n let configured = false;\n for (const path of paths) {\n if (\n await matchGritQL(\n tree,\n path,\n 'language hcl\\n`required_providers { $_ }`',\n )\n ) {\n requirementPath ??= path;\n }\n configured ||= await matchGritQL(\n tree,\n path,\n 'language hcl\\n`provider \"awscc\" { $config }` where { $config <: not contains `alias = $_` }',\n );\n }\n if (!requirementPath) {\n requirementPath = joinPathFragments(root, 'greengrass-providers.tf');\n if (tree.exists(requirementPath)) {\n throw new Error(\n `Cannot add awscc required_providers: ${requirementPath} already exists without a terraform block. Configure awscc in the root module.`,\n );\n }\n tree.write(\n requirementPath,\n `terraform {\\n required_providers {\\n ${requirement}\\n }\\n}\\n`,\n );\n } else {\n const filledEmptyBlock = await applyGritQL(\n tree,\n requirementPath,\n `language hcl\\n\\`required_providers {}\\` => \\`required_providers {\\n ${requirement}\\n }\\``,\n );\n if (!filledEmptyBlock) {\n await applyGritQL(\n tree,\n requirementPath,\n 'language hcl\\n`required_providers { $providers }` where { ' +\n '$providers <: not contains `awscc = $_`, ' +\n `$providers += \\`\\n ${requirement}\\` }`,\n );\n }\n }\n if (!configured) {\n tree.write(\n requirementPath,\n `${tree.read(requirementPath, 'utf-8')!.trimEnd()}\\n\\nprovider \"awscc\" {\\n region = var.aws_region\\n}\\n`,\n );\n }\n }\n};\n\n/** Registers `projectName`'s artifact target on the shared iac project the caller vended into. */\nconst addArtifactProjectToSharedTargets = (\n tree: Tree,\n iac: Iac,\n projectName: string,\n): void => {\n updateJson(\n tree,\n joinPathFragments(\n PACKAGES_DIR,\n iac === 'cdk' ? SHARED_CONSTRUCTS_DIR : SHARED_TERRAFORM_DIR,\n 'project.json',\n ),\n (config: ProjectConfiguration) => {\n addArtifactProjectToTargets(config, projectName);\n return config;\n },\n );\n};\n\n/**\n * Vends the shared `GreengrassArtifactBucket` / `GreengrassComponentVersion` /\n * `GreengrassDeployment` / recipe-reader constructs (CDK) or modules\n * (Terraform, via the `hashicorp/awscc` provider - neither\n * `AWS::GreengrassV2::ComponentVersion` nor `AWS::GreengrassV2::Deployment`\n * exists in the pinned `hashicorp/aws` provider) into\n * `common/constructs/src/core/greengrass/` or\n * `common/terraform/src/core/greengrass/`. Existing core files are preserved\n * on later component runs; missing files are added. Idempotent: called from\n * every component generator run.\n */\nexport const addGreengrassCoreConstructs = async <\n const D extends DependencyDeclaration,\n>(\n tree: Tree,\n { iac }: { iac: Iac },\n declaration: D & MustDeclare<typeof GREENGRASS_CONSTRUCTS_DEPENDENCIES, D>,\n): Promise<void> => {\n const componentName = buildDefaultComponentName(tree, 'Namespace');\n const componentKeyPrefix = `${componentName.slice(0, componentName.lastIndexOf('.'))}.*`;\n if (iac === 'terraform') {\n await configureGreengrassTerraformProviders(tree);\n generateFiles(\n tree,\n joinPathFragments(\n import.meta.dirname,\n 'files',\n 'terraform',\n 'core',\n 'greengrass',\n ),\n CORE_GREENGRASS_TERRAFORM_DIR,\n { ...terraformProviderVersions(), componentKeyPrefix },\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n return;\n }\n if (iac !== 'cdk') {\n throw new Error(`Unsupported iac ${iac}`);\n }\n\n generateFiles(\n tree,\n joinPathFragments(\n import.meta.dirname,\n 'files',\n 'cdk',\n 'core',\n 'greengrass',\n ),\n CORE_GREENGRASS_DIR,\n { ...esmVars(tree), ...cdkLambdaRuntimeVars(), componentKeyPrefix },\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', 'next-version'),\n joinPathFragments(CORE_GREENGRASS_DIR, 'next-version'),\n { nextVersionFileName: 'index.js' },\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n\n await addStarExport(\n tree,\n joinPathFragments(\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n 'src',\n 'core',\n 'index.ts',\n ),\n './greengrass/index.js',\n );\n\n addDependenciesToPackageJson(\n tree,\n withVersions(\n forDependencies<typeof GREENGRASS_CONSTRUCTS_DEPENDENCIES>(declaration),\n ['js-yaml', '@aws-sdk/client-greengrassv2'],\n ),\n withVersions(\n forDependencies<typeof GREENGRASS_CONSTRUCTS_DEPENDENCIES>(declaration),\n ['@types/js-yaml'],\n ),\n joinPathFragments(PACKAGES_DIR, SHARED_CONSTRUCTS_DIR, 'package.json'),\n );\n};\n\nexport interface AddGreengrassComponentAppConstructOptions {\n readonly iac: Iac;\n readonly componentNameClassName: string;\n readonly componentDisplayName: string;\n readonly componentDirName: string;\n readonly project: string;\n /** The host project whose `<c>-artifact` target this construct reads at synth time. */\n readonly hostProjectName: string;\n readonly recipesDirFromRoot: string;\n readonly artifactsDirFromRoot: string;\n}\n\n/**\n * Vends the per-component app construct/module: a thin\n * `GreengrassComponentVersion` wrapper pinning this component's build output\n * paths, at `common/constructs/src/app/greengrass/<componentDirName>.ts`\n * (CDK) or `common/terraform/src/app/greengrass-component/<componentDirName>/`\n * (Terraform, taking the artifact bucket's name as a plain input variable so\n * user IaC can own or import the shared artifact repository).\n * `OverwriteStrategy.KeepExisting` either way. Registers the host project on\n * the shared iac project's `build`/`assemble` targets so `nx run\n * <infra>:deploy` always deploys a freshly built artifact.\n */\nexport const addGreengrassComponentAppConstruct = async <\n const D extends DependencyDeclaration,\n>(\n tree: Tree,\n options: AddGreengrassComponentAppConstructOptions,\n declaration: D & MustDeclare<typeof GREENGRASS_CONSTRUCTS_DEPENDENCIES, D>,\n): Promise<void> => {\n await addGreengrassCoreConstructs(\n tree,\n { iac: options.iac },\n forDependencies<typeof GREENGRASS_CONSTRUCTS_DEPENDENCIES>(declaration),\n );\n\n if (options.iac === 'terraform') {\n generateFiles(\n tree,\n joinPathFragments(\n import.meta.dirname,\n 'files',\n 'terraform',\n 'app',\n 'greengrass-component',\n ),\n APP_GREENGRASS_COMPONENT_TERRAFORM_DIR,\n options,\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n addArtifactProjectToSharedTargets(\n tree,\n 'terraform',\n options.hostProjectName,\n );\n return;\n }\n\n generateFiles(\n tree,\n joinPathFragments(\n import.meta.dirname,\n 'files',\n 'cdk',\n 'app',\n 'greengrass-component',\n ),\n APP_GREENGRASS_DIR,\n { ...options, ...esmVars(tree) },\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n\n await addStarExport(\n tree,\n joinPathFragments(APP_GREENGRASS_DIR, 'index.ts'),\n `./${options.componentDirName}.js`,\n );\n await addStarExport(\n tree,\n joinPathFragments(\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n 'src',\n 'app',\n 'index.ts',\n ),\n './greengrass/index.js',\n );\n\n addArtifactProjectToSharedTargets(tree, 'cdk', options.hostProjectName);\n};\n"],"names":["generateFiles","getProjects","joinPathFragments","logger","OverwriteStrategy","updateJson","addStarExport","applyGritQL","matchGritQL","forDependencies","addDependenciesToPackageJson","buildDefaultComponentName","esmVars","addArtifactProjectToTargets","PACKAGES_DIR","SHARED_CONSTRUCTS_DIR","SHARED_TERRAFORM_DIR","cdkLambdaRuntimeVars","terraformProviderVersions","withVersions","GREENGRASS_CONSTRUCTS_DEPENDENCIES","name","when","m","iac","dev","CORE_GREENGRASS_DIR","APP_GREENGRASS_DIR","CORE_GREENGRASS_TERRAFORM_DIR","APP_GREENGRASS_COMPONENT_TERRAFORM_DIR","configureGreengrassTerraformProviders","tree","roots","values","filter","project","projectType","map","sourceRoot","root","children","some","endsWith","length","warn","paths","requirement","awsccProviderVersion","requirementPath","configured","path","exists","Error","write","filledEmptyBlock","read","trimEnd","addArtifactProjectToSharedTargets","projectName","config","addGreengrassCoreConstructs","declaration","componentName","componentKeyPrefix","slice","lastIndexOf","dirname","overwriteStrategy","KeepExisting","nextVersionFileName","addGreengrassComponentAppConstruct","options","hostProjectName","componentDirName"],"mappings":"AAAA;;;CAGC,GACD,SACEA,aAAa,EACbC,WAAW,EACXC,iBAAiB,EACjBC,MAAM,EACNC,iBAAiB,EAGjBC,UAAU,QACL,aAAa;AACpB,SAASC,aAAa,EAAEC,WAAW,EAAEC,WAAW,QAAQ,YAAY;AAKpE,SAASC,eAAe,QAAQ,8BAA8B;AAC9D,SAASC,4BAA4B,QAAQ,qBAAqB;AAClE,SAASC,yBAAyB,QAAQ,0BAA0B;AAEpE,SAASC,OAAO,QAAQ,sBAAsB;AAC9C,SAASC,2BAA2B,QAAQ,WAAW;AAEvD,SACEC,YAAY,EACZC,qBAAqB,EACrBC,oBAAoB,QACf,oCAAoC;AAC3C,SACEC,oBAAoB,EAEpBC,yBAAyB,EACzBC,YAAY,QACP,iBAAiB;AAExB,0EAA0E,GAC1E,OAAO,MAAMC,qCAAqC;IAChD;QAAEC,MAAM;QAAWC,MAAM,CAACC,IAAmBA,EAAEC,GAAG,KAAK;IAAM;IAC7D;QACEH,MAAM;QACNI,KAAK;QACLH,MAAM,CAACC,IAAmBA,EAAEC,GAAG,KAAK;IACtC;IACA;QACEH,MAAM;QACNC,MAAM,CAACC,IAAmBA,EAAEC,GAAG,KAAK;IACtC;CACD,CAKG;AAEJ,MAAME,sBAAsBxB,kBAC1BY,cACAC,uBACA,OACA,QACA;AAEF,MAAMY,qBAAqBzB,kBACzBY,cACAC,uBACA,OACA,OACA;AAEF,MAAMa,gCAAgC1B,kBACpCY,cACAE,sBACA,OACA,QACA;AAEF,MAAMa,yCAAyC3B,kBAC7CY,cACAE,sBACA,OACA,OACA;AAEF,kFAAkF,GAClF,MAAMc,wCAAwC,OAC5CC;IAEA,MAAMC,QAAQ;WAAI/B,YAAY8B,MAAME,MAAM;KAAG,CAC1CC,MAAM,CAAC,CAACC,UAAYA,QAAQC,WAAW,KAAK,eAC5CC,GAAG,CACF,CAACF,UAAYA,QAAQG,UAAU,IAAIpC,kBAAkBiC,QAAQI,IAAI,EAAE,QAEpEL,MAAM,CAAC,CAACK,OAASR,KAAKS,QAAQ,CAACD,MAAME,IAAI,CAAC,CAACpB,OAASA,KAAKqB,QAAQ,CAAC;IACrE,IAAIV,MAAMW,MAAM,KAAK,GAAG;QACtBxC,OAAOyC,IAAI,CACT,gGACE;IAEN;IACA,KAAK,MAAML,QAAQP,MAAO;QACxB,MAAMa,QAAQd,KACXS,QAAQ,CAACD,MACTL,MAAM,CAAC,CAACb,OAASA,KAAKqB,QAAQ,CAAC,QAC/BL,GAAG,CAAC,CAAChB,OAASnB,kBAAkBqC,MAAMlB;QACzC,MAAMyB,cAAc,CAAC;;iBAER,EAAE5B,4BAA4B6B,oBAAoB,CAAC;KAC/D,CAAC;QACF,IAAIC;QACJ,IAAIC,aAAa;QACjB,KAAK,MAAMC,QAAQL,MAAO;YACxB,IACE,MAAMrC,YACJuB,MACAmB,MACA,8CAEF;gBACAF,oBAAoBE;YACtB;YACAD,eAAe,MAAMzC,YACnBuB,MACAmB,MACA;QAEJ;QACA,IAAI,CAACF,iBAAiB;YACpBA,kBAAkB9C,kBAAkBqC,MAAM;YAC1C,IAAIR,KAAKoB,MAAM,CAACH,kBAAkB;gBAChC,MAAM,IAAII,MACR,CAAC,qCAAqC,EAAEJ,gBAAgB,8EAA8E,CAAC;YAE3I;YACAjB,KAAKsB,KAAK,CACRL,iBACA,CAAC,yCAAyC,EAAEF,YAAY,UAAU,CAAC;QAEvE,OAAO;YACL,MAAMQ,mBAAmB,MAAM/C,YAC7BwB,MACAiB,iBACA,CAAC,uEAAuE,EAAEF,YAAY,OAAO,CAAC;YAEhG,IAAI,CAACQ,kBAAkB;gBACrB,MAAM/C,YACJwB,MACAiB,iBACA,+DACE,8CACA,CAAC,sBAAsB,EAAEF,YAAY,IAAI,CAAC;YAEhD;QACF;QACA,IAAI,CAACG,YAAY;YACflB,KAAKsB,KAAK,CACRL,iBACA,GAAGjB,KAAKwB,IAAI,CAACP,iBAAiB,SAAUQ,OAAO,GAAG,sDAAsD,CAAC;QAE7G;IACF;AACF;AAEA,gGAAgG,GAChG,MAAMC,oCAAoC,CACxC1B,MACAP,KACAkC;IAEArD,WACE0B,MACA7B,kBACEY,cACAU,QAAQ,QAAQT,wBAAwBC,sBACxC,iBAEF,CAAC2C;QACC9C,4BAA4B8C,QAAQD;QACpC,OAAOC;IACT;AAEJ;AAEA;;;;;;;;;;CAUC,GACD,OAAO,MAAMC,8BAA8B,OAGzC7B,MACA,EAAEP,GAAG,EAAgB,EACrBqC;IAEA,MAAMC,gBAAgBnD,0BAA0BoB,MAAM;IACtD,MAAMgC,qBAAqB,GAAGD,cAAcE,KAAK,CAAC,GAAGF,cAAcG,WAAW,CAAC,MAAM,EAAE,CAAC;IACxF,IAAIzC,QAAQ,aAAa;QACvB,MAAMM,sCAAsCC;QAC5C/B,cACE+B,MACA7B,kBACE,YAAYgE,OAAO,EACnB,SACA,aACA,QACA,eAEFtC,+BACA;YAAE,GAAGV,2BAA2B;YAAE6C;QAAmB,GACrD;YAAEI,mBAAmB/D,kBAAkBgE,YAAY;QAAC;QAEtD;IACF;IACA,IAAI5C,QAAQ,OAAO;QACjB,MAAM,IAAI4B,MAAM,CAAC,gBAAgB,EAAE5B,KAAK;IAC1C;IAEAxB,cACE+B,MACA7B,kBACE,YAAYgE,OAAO,EACnB,SACA,OACA,QACA,eAEFxC,qBACA;QAAE,GAAGd,QAAQmB,KAAK;QAAE,GAAGd,sBAAsB;QAAE8C;IAAmB,GAClE;QAAEI,mBAAmB/D,kBAAkBgE,YAAY;IAAC;IAEtDpE,cACE+B,MACA7B,kBAAkB,YAAYgE,OAAO,EAAE,SAAS,iBAChDhE,kBAAkBwB,qBAAqB,iBACvC;QAAE2C,qBAAqB;IAAW,GAClC;QAAEF,mBAAmB/D,kBAAkBgE,YAAY;IAAC;IAGtD,MAAM9D,cACJyB,MACA7B,kBACEY,cACAC,uBACA,OACA,QACA,aAEF;IAGFL,6BACEqB,MACAZ,aACEV,gBAA2DoD,cAC3D;QAAC;QAAW;KAA+B,GAE7C1C,aACEV,gBAA2DoD,cAC3D;QAAC;KAAiB,GAEpB3D,kBAAkBY,cAAcC,uBAAuB;AAE3D,EAAE;AAcF;;;;;;;;;;CAUC,GACD,OAAO,MAAMuD,qCAAqC,OAGhDvC,MACAwC,SACAV;IAEA,MAAMD,4BACJ7B,MACA;QAAEP,KAAK+C,QAAQ/C,GAAG;IAAC,GACnBf,gBAA2DoD;IAG7D,IAAIU,QAAQ/C,GAAG,KAAK,aAAa;QAC/BxB,cACE+B,MACA7B,kBACE,YAAYgE,OAAO,EACnB,SACA,aACA,OACA,yBAEFrC,wCACA0C,SACA;YAAEJ,mBAAmB/D,kBAAkBgE,YAAY;QAAC;QAEtDX,kCACE1B,MACA,aACAwC,QAAQC,eAAe;QAEzB;IACF;IAEAxE,cACE+B,MACA7B,kBACE,YAAYgE,OAAO,EACnB,SACA,OACA,OACA,yBAEFvC,oBACA;QAAE,GAAG4C,OAAO;QAAE,GAAG3D,QAAQmB,KAAK;IAAC,GAC/B;QAAEoC,mBAAmB/D,kBAAkBgE,YAAY;IAAC;IAGtD,MAAM9D,cACJyB,MACA7B,kBAAkByB,oBAAoB,aACtC,CAAC,EAAE,EAAE4C,QAAQE,gBAAgB,CAAC,GAAG,CAAC;IAEpC,MAAMnE,cACJyB,MACA7B,kBACEY,cACAC,uBACA,OACA,OACA,aAEF;IAGF0C,kCAAkC1B,MAAM,OAAOwC,QAAQC,eAAe;AACxE,EAAE"}
|
|
@@ -8,6 +8,10 @@ terraform {
|
|
|
8
8
|
source = "hashicorp/random"
|
|
9
9
|
version = "<%- randomProviderVersion %>"
|
|
10
10
|
}
|
|
11
|
+
time = {
|
|
12
|
+
source = "hashicorp/time"
|
|
13
|
+
version = "<%- timeProviderVersion %>"
|
|
14
|
+
}
|
|
11
15
|
}
|
|
12
16
|
}
|
|
13
17
|
|
|
@@ -72,12 +76,25 @@ resource "aws_bedrock_guardrail_version" "this" {
|
|
|
72
76
|
}
|
|
73
77
|
}
|
|
74
78
|
|
|
79
|
+
resource "time_sleep" "version_retention" {
|
|
80
|
+
destroy_duration = "15s"
|
|
81
|
+
|
|
82
|
+
triggers = {
|
|
83
|
+
guardrail_id = aws_bedrock_guardrail.this.guardrail_id
|
|
84
|
+
guardrail_version = aws_bedrock_guardrail_version.this.version
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
lifecycle {
|
|
88
|
+
create_before_destroy = true
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
75
92
|
module "add_guardrail_to_runtime_config" {
|
|
76
93
|
source = "../../../core/runtime-config/entry"
|
|
77
94
|
|
|
78
95
|
namespace = "agentcore"
|
|
79
96
|
key = "guardrails"
|
|
80
|
-
value = { "<%= nameClassName %>" = { guardrailId =
|
|
97
|
+
value = { "<%= nameClassName %>" = { guardrailId = time_sleep.version_retention.triggers.guardrail_id, guardrailVersion = time_sleep.version_retention.triggers.guardrail_version } }
|
|
81
98
|
}
|
|
82
99
|
|
|
83
100
|
output "guardrail_id" {
|
|
@@ -16,6 +16,11 @@ export interface AddGuardrailInfraOptions {
|
|
|
16
16
|
/** Workspace-root-relative path of the guardrail.json policy file. */
|
|
17
17
|
policyPath: string;
|
|
18
18
|
}
|
|
19
|
+
/**
|
|
20
|
+
* Write the guardrail.json policy next to the agent. The policy is the
|
|
21
|
+
* user's to edit, so a re-run never touches an existing file.
|
|
22
|
+
*/
|
|
23
|
+
export declare const addGuardrailPolicy: (tree: Tree, agentDir: string) => void;
|
|
19
24
|
/**
|
|
20
25
|
* Add the Amazon Bedrock Guardrail infrastructure for the selected IaC
|
|
21
26
|
* provider: a CDK construct in the shared constructs project, or a Terraform
|
|
@@ -6,6 +6,14 @@ import { addStarExport } from "../ast.js";
|
|
|
6
6
|
import { esmVars } from "../module-format.js";
|
|
7
7
|
import { PACKAGES_DIR, SHARED_CONSTRUCTS_DIR, SHARED_TERRAFORM_DIR } from "../shared-constructs-constants.js";
|
|
8
8
|
import { terraformProviderVersions } from "../versions.js";
|
|
9
|
+
/**
|
|
10
|
+
* Write the guardrail.json policy next to the agent. The policy is the
|
|
11
|
+
* user's to edit, so a re-run never touches an existing file.
|
|
12
|
+
*/ export const addGuardrailPolicy = (tree, agentDir)=>{
|
|
13
|
+
generateFiles(tree, joinPathFragments(import.meta.dirname, 'files', 'policy'), agentDir, {}, {
|
|
14
|
+
overwriteStrategy: OverwriteStrategy.KeepExisting
|
|
15
|
+
});
|
|
16
|
+
};
|
|
9
17
|
/**
|
|
10
18
|
* Add the Amazon Bedrock Guardrail infrastructure for the selected IaC
|
|
11
19
|
* provider: a CDK construct in the shared constructs project, or a Terraform
|