@intentius/chant-lexicon-aws 0.124.45 → 0.124.48
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/dist/capabilities/mapping.json +150 -0
- package/dist/capabilities/pack.d.ts +8 -0
- package/dist/capabilities/pack.d.ts.map +1 -0
- package/dist/capabilities/pack.js +2 -0
- package/dist/components/capability-plugin.d.ts +1 -1
- package/dist/components/capability-plugin.d.ts.map +1 -1
- package/dist/components/capability-plugin.js +6 -4
- package/dist/components/publish.d.ts +28 -97
- package/dist/components/publish.d.ts.map +1 -1
- package/dist/components/publish.js +42 -109
- package/dist/integrity.json +2 -2
- package/dist/manifest.json +1 -1
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +2 -0
- package/package.json +2 -2
- package/src/capabilities/mapping.json +150 -0
- package/src/capabilities/pack.ts +9 -0
- package/src/capabilities.test.ts +182 -0
- package/src/components/capability-plugin.ts +6 -4
- package/src/components/publish.ts +61 -193
- package/src/graph-sub-edges.test.ts +101 -0
- package/src/plugin.ts +2 -0
- package/src/testdata/capabilities-ledger/estate.ts +161 -0
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
{
|
|
2
|
+
"lexicon": "aws",
|
|
3
|
+
"types": "kind",
|
|
4
|
+
"refs": "cloudformation",
|
|
5
|
+
"labels": {
|
|
6
|
+
"AWS::EC2::VPC": "Vpc",
|
|
7
|
+
"AWS::EC2::NetworkInterface": "NetworkInterface",
|
|
8
|
+
"AWS::EC2::Volume": "Volume",
|
|
9
|
+
"AWS::Lambda::Function": "Function",
|
|
10
|
+
"AWS::Lambda::Url": "FunctionUrl",
|
|
11
|
+
"AWS::IAM::InstanceProfile": "InstanceProfile",
|
|
12
|
+
"AWS::IAM::Role": "Role",
|
|
13
|
+
"AWS::IAM::Policy": "Policy",
|
|
14
|
+
"AWS::IAM::ManagedPolicy": "Policy",
|
|
15
|
+
"AWS::S3::BucketPolicy": "ResourcePolicy",
|
|
16
|
+
"AWS::SQS::QueuePolicy": "ResourcePolicy",
|
|
17
|
+
"AWS::S3::Bucket": "Bucket",
|
|
18
|
+
"AWS::DynamoDB::Table": "Table",
|
|
19
|
+
"AWS::DynamoDB::GlobalTable": "Table",
|
|
20
|
+
"AWS::RDS::DBInstance": "Database",
|
|
21
|
+
"AWS::RDS::DBCluster": "Database",
|
|
22
|
+
"AWS::SecretsManager::Secret": "Secret",
|
|
23
|
+
"AWS::SQS::Queue": "Queue",
|
|
24
|
+
"AWS::EFS::FileSystem": "FileSystem",
|
|
25
|
+
"AWS::SSM::Parameter": "Parameter",
|
|
26
|
+
"AWS::ECS::Service": "Service",
|
|
27
|
+
"AWS::ECS::TaskDefinition": "TaskDefinition",
|
|
28
|
+
"AWS::RDS::DBSubnetGroup": "SubnetGroup",
|
|
29
|
+
"AWS::EC2::NatGateway": "NatGateway",
|
|
30
|
+
"AWS::ElasticLoadBalancingV2::LoadBalancer": "LoadBalancer"
|
|
31
|
+
},
|
|
32
|
+
"edges": {
|
|
33
|
+
"Instance": {
|
|
34
|
+
"IamInstanceProfile": "profile",
|
|
35
|
+
"VpcId": "vpc"
|
|
36
|
+
},
|
|
37
|
+
"LaunchTemplate": {
|
|
38
|
+
"LaunchTemplateData": {
|
|
39
|
+
"InstanceProfile": "profile"
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
"Subnet": {
|
|
43
|
+
"VpcId": "vpc"
|
|
44
|
+
},
|
|
45
|
+
"SecurityGroup": {
|
|
46
|
+
"VpcId": "vpc"
|
|
47
|
+
},
|
|
48
|
+
"NetworkInterface": {
|
|
49
|
+
"SubnetId": "subnet",
|
|
50
|
+
"GroupSet": "sg"
|
|
51
|
+
},
|
|
52
|
+
"Database": {
|
|
53
|
+
"VPCSecurityGroups": "sg",
|
|
54
|
+
"VpcSecurityGroupIds": "sg",
|
|
55
|
+
"DBSubnetGroupName": "subnetGroup"
|
|
56
|
+
},
|
|
57
|
+
"Function": {
|
|
58
|
+
"Role": "role",
|
|
59
|
+
"VpcConfig": {
|
|
60
|
+
"SecurityGroup": "sg",
|
|
61
|
+
"Subnet": "subnet"
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
"FunctionUrl": {
|
|
65
|
+
"TargetFunctionArn": "function"
|
|
66
|
+
},
|
|
67
|
+
"InstanceProfile": {
|
|
68
|
+
"Roles": "role"
|
|
69
|
+
},
|
|
70
|
+
"Policy": {
|
|
71
|
+
"Roles": "attachedTo"
|
|
72
|
+
},
|
|
73
|
+
"Role": {
|
|
74
|
+
"ManagedPolicyArns": "-attachedTo"
|
|
75
|
+
},
|
|
76
|
+
"ResourcePolicy": {
|
|
77
|
+
"Bucket": "policyOf",
|
|
78
|
+
"Queues": "policyOf"
|
|
79
|
+
},
|
|
80
|
+
"Service": {
|
|
81
|
+
"TaskDefinition": "task",
|
|
82
|
+
"NetworkConfiguration": {
|
|
83
|
+
"SecurityGroup": "sg",
|
|
84
|
+
"Subnet": "subnet"
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
"TaskDefinition": {
|
|
88
|
+
"TaskRoleArn": "role"
|
|
89
|
+
},
|
|
90
|
+
"SubnetGroup": {
|
|
91
|
+
"SubnetIds": "subnet"
|
|
92
|
+
},
|
|
93
|
+
"NatGateway": {
|
|
94
|
+
"SubnetId": "subnet"
|
|
95
|
+
},
|
|
96
|
+
"LoadBalancer": {
|
|
97
|
+
"Subnets": "subnet",
|
|
98
|
+
"SecurityGroups": "sg"
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
"attrs": {
|
|
102
|
+
"FunctionUrl": {
|
|
103
|
+
"authType": "AuthType"
|
|
104
|
+
},
|
|
105
|
+
"Role": {
|
|
106
|
+
"name": "RoleName"
|
|
107
|
+
},
|
|
108
|
+
"Bucket": {
|
|
109
|
+
"name": "BucketName",
|
|
110
|
+
"acl": "AccessControl",
|
|
111
|
+
"blockPublicPolicy": "PublicAccessBlockConfiguration.BlockPublicPolicy"
|
|
112
|
+
},
|
|
113
|
+
"Table": {
|
|
114
|
+
"name": "TableName"
|
|
115
|
+
},
|
|
116
|
+
"Database": {
|
|
117
|
+
"encrypted": "StorageEncrypted"
|
|
118
|
+
},
|
|
119
|
+
"FileSystem": {
|
|
120
|
+
"encrypted": "Encrypted"
|
|
121
|
+
},
|
|
122
|
+
"Volume": {
|
|
123
|
+
"encrypted": "Encrypted"
|
|
124
|
+
},
|
|
125
|
+
"Parameter": {
|
|
126
|
+
"paramType": "Type"
|
|
127
|
+
},
|
|
128
|
+
"Vpc": {
|
|
129
|
+
"isDefault": "IsDefault"
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
"documents": {
|
|
133
|
+
"Role": {
|
|
134
|
+
"AssumeRolePolicyDocument": "trust",
|
|
135
|
+
"Policies[].PolicyDocument": "permission"
|
|
136
|
+
},
|
|
137
|
+
"Policy": {
|
|
138
|
+
"PolicyDocument": "permission"
|
|
139
|
+
},
|
|
140
|
+
"ResourcePolicy": {
|
|
141
|
+
"PolicyDocument": "resource"
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
"tags": [
|
|
145
|
+
"Tags"
|
|
146
|
+
],
|
|
147
|
+
"classificationTags": [
|
|
148
|
+
"data-classification"
|
|
149
|
+
]
|
|
150
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The aws lexicon's capability pack (#4375): its mapping of CloudFormation
|
|
3
|
+
* kinds onto the lexicon-neutral view the capability rules read. All data;
|
|
4
|
+
* CloudFormation policy documents are JSON already, so no adapter code.
|
|
5
|
+
*/
|
|
6
|
+
import type { CapabilityPack } from "@intentius/chant/capabilities/view";
|
|
7
|
+
export declare const awsCapabilityPack: CapabilityPack;
|
|
8
|
+
//# sourceMappingURL=pack.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pack.d.ts","sourceRoot":"","sources":["../../src/capabilities/pack.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAqB,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAG5F,eAAO,MAAM,iBAAiB,EAAE,cAA0D,CAAC"}
|
|
@@ -11,7 +11,7 @@ import { type CapabilityPlugin } from "@intentius/chant/components/capability-pl
|
|
|
11
11
|
/** The AWS verb families this plugin contributes, grouped for `families()` — mirrors core's `STARTER_VERB_FAMILIES` shape. */
|
|
12
12
|
export declare const AWS_VERB_FAMILIES: {
|
|
13
13
|
readonly sbom: readonly ["extract-config-bom"];
|
|
14
|
-
readonly publish: readonly ["
|
|
14
|
+
readonly publish: readonly ["load-image-on-host"];
|
|
15
15
|
readonly apply: readonly ["cfn-deploy", "ecs-update-service", "lambda-deploy", "s3-sync", "cdn-invalidate", "run-migration"];
|
|
16
16
|
readonly jobSubmission: readonly ["emr-start-job-run", "emr-submit-step"];
|
|
17
17
|
readonly hostDelivery: readonly ["code-deploy", "copy-to-host", "remote-exec"];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"capability-plugin.d.ts","sourceRoot":"","sources":["../../src/components/capability-plugin.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAqB,KAAK,gBAAgB,EAAE,MAAM,+CAA+C,CAAC;AAiBzG,8HAA8H;AAC9H,eAAO,MAAM,iBAAiB;aAE5B,IAAI,YAAG,oBAAoB;
|
|
1
|
+
{"version":3,"file":"capability-plugin.d.ts","sourceRoot":"","sources":["../../src/components/capability-plugin.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAqB,KAAK,gBAAgB,EAAE,MAAM,+CAA+C,CAAC;AAiBzG,8HAA8H;AAC9H,eAAO,MAAM,iBAAiB;aAE5B,IAAI,YAAG,oBAAoB;aAG3B,OAAO,YAAG,oBAAoB;aAC9B,KAAK,YAAG,YAAY,EAAE,oBAAoB,EAAE,eAAe,EAAE,SAAS,EAAE,gBAAgB,EAAE,eAAe;aACzG,aAAa,YAAG,mBAAmB,EAAE,iBAAiB;aACtD,YAAY,YAAG,aAAa,EAAE,cAAc,EAAE,aAAa;aAC3D,UAAU,YAAG,gBAAgB,EAAE,mBAAmB,EAAE,UAAU;aAC9D,MAAM,YAAG,iBAAiB,EAAE,mBAAmB;CACvC,CAAC;AA0BX,yHAAyH;AACzH,eAAO,MAAM,mBAAmB,EAAE,gBAajC,CAAC"}
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* set carries only the agnostic verbs; the cloud leaves live here.
|
|
9
9
|
*/
|
|
10
10
|
import { ownPackageVersion } from "@intentius/chant/components/capability-plugin";
|
|
11
|
-
import {
|
|
11
|
+
import { ecrRegistryBackend, s3StorageBackend, loadImageOnHostCapability } from "./publish.js";
|
|
12
12
|
import { extractConfigBomCapability } from "./config-bom.js";
|
|
13
13
|
import { cfnDeployCapability, ecsUpdateServiceCapability, lambdaDeployCapability, s3SyncCapability, cdnInvalidateCapability, runMigrationCapability, } from "./apply.js";
|
|
14
14
|
import { emrStartJobRunCapability, emrSubmitStepCapability } from "./job-submission.js";
|
|
@@ -19,7 +19,9 @@ import { snapshotBeforeCapability, rollbackPreviousCapability } from "./safety.j
|
|
|
19
19
|
export const AWS_VERB_FAMILIES = {
|
|
20
20
|
// `extract-config-bom` parses a synthesized CloudFormation template (#684).
|
|
21
21
|
sbom: ["extract-config-bom"],
|
|
22
|
-
|
|
22
|
+
// `publish-image` is core's verb (#3142, #3143); aws contributes its ECR login as a registry backend.
|
|
23
|
+
// `publish-artifact` is core's verb (#4408); aws contributes S3 as a storage backend.
|
|
24
|
+
publish: ["load-image-on-host"],
|
|
23
25
|
apply: ["cfn-deploy", "ecs-update-service", "lambda-deploy", "s3-sync", "cdn-invalidate", "run-migration"],
|
|
24
26
|
jobSubmission: ["emr-start-job-run", "emr-submit-step"],
|
|
25
27
|
hostDelivery: ["code-deploy", "copy-to-host", "remote-exec"],
|
|
@@ -30,9 +32,7 @@ export const AWS_VERB_FAMILIES = {
|
|
|
30
32
|
function awsCapabilities() {
|
|
31
33
|
return [
|
|
32
34
|
extractConfigBomCapability,
|
|
33
|
-
publishImageCapability,
|
|
34
35
|
loadImageOnHostCapability,
|
|
35
|
-
publishArtifactCapability,
|
|
36
36
|
cfnDeployCapability,
|
|
37
37
|
ecsUpdateServiceCapability,
|
|
38
38
|
lambdaDeployCapability,
|
|
@@ -62,5 +62,7 @@ export const awsCapabilityPlugin = {
|
|
|
62
62
|
return ownPackageVersion(import.meta.url);
|
|
63
63
|
},
|
|
64
64
|
capabilities: awsCapabilities,
|
|
65
|
+
registryBackends: () => [ecrRegistryBackend],
|
|
66
|
+
storageBackends: () => [s3StorageBackend],
|
|
65
67
|
families: () => AWS_VERB_FAMILIES,
|
|
66
68
|
};
|
|
@@ -47,89 +47,25 @@
|
|
|
47
47
|
import type { Capability } from "@intentius/chant/components/capability";
|
|
48
48
|
import { type CloudExecutor } from "./cloud-executor.js";
|
|
49
49
|
import { type ProcessRunner } from "@intentius/chant/components/verbs/process-runner";
|
|
50
|
+
import { type PublishImageBackend, type RegistryLoginBackend } from "@intentius/chant/components/verbs/publish-image";
|
|
51
|
+
import { type ArtifactStorageBackend, type PublishArtifactInput, type PublishArtifactOutput } from "@intentius/chant/components/verbs/publish-artifact";
|
|
52
|
+
export type { PublishImageInput, PublishImageOutput, PublishImageBackend, ReferrerAttachResult, } from "@intentius/chant/components/verbs/publish-image";
|
|
50
53
|
/**
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
* one backend, so a component authors one step shape (see
|
|
55
|
-
* docs/components/build-archive.mdx) and the env-selected backend (see
|
|
56
|
-
* `selectPublishBackend` below) reads whichever field it needs — the
|
|
57
|
-
* unselected backend's field is simply unused, never a pipeline fork.
|
|
54
|
+
* The aws lexicon's registry login for core's `publish-image` (#3142, #3143):
|
|
55
|
+
* `aws ecr get-login-password | docker login`. The aws plugin contributes it;
|
|
56
|
+
* core owns load, tag, push and the digest read-back.
|
|
58
57
|
*/
|
|
59
|
-
export
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
/** Destination registry — required by `publish-image`, ignored by `load-image-on-host` (e.g. `$env.registry` resolved by the orchestrator). */
|
|
63
|
-
to?: string;
|
|
64
|
-
/** Target host — required by `load-image-on-host`, ignored by `publish-image` (SSM instance id, hostname, or host group). */
|
|
65
|
-
host?: string;
|
|
66
|
-
/** Destination path for the tarball on the host, used only by `load-image-on-host`. Default: `/tmp/chant-archive/<basename of from>`. */
|
|
67
|
-
hostPath?: string;
|
|
68
|
-
/** Additional tags to apply alongside the digest, used only by `publish-image`. */
|
|
69
|
-
tags?: string[];
|
|
70
|
-
/**
|
|
71
|
-
* #610: the artifact's software SBOM (typically wired from a prior
|
|
72
|
-
* `generate-sbom` step's `sbom` output — see ./sbom.ts's
|
|
73
|
-
* `GenerateSbomOutput`) to attach as an OCI referrer on the pushed image
|
|
74
|
-
* digest, via `oras attach`. Used only by `publish-image`; ignored by
|
|
75
|
-
* `load-image-on-host` (registry-less — nothing to attach to). Omit to
|
|
76
|
-
* skip the attach step entirely (the archive-carried copy remains the
|
|
77
|
-
* SBOM's home either way).
|
|
78
|
-
*/
|
|
79
|
-
sbom?: {
|
|
80
|
-
bytes: string;
|
|
81
|
-
mediaType: string;
|
|
82
|
-
};
|
|
83
|
-
/**
|
|
84
|
-
* #610: the component-level aggregate BOM (wired from
|
|
85
|
-
* ./component-bom.ts's `aggregateComponentBom` output), attached as a
|
|
86
|
-
* second OCI referrer alongside `sbom` when supplied. Optional and
|
|
87
|
-
* independent of `sbom` — a caller may attach either, both, or neither.
|
|
88
|
-
*/
|
|
89
|
-
componentBom?: {
|
|
90
|
-
bytes: string;
|
|
91
|
-
mediaType: string;
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
|
-
/** Result of `publish-image`'s best-effort OCI-referrer attach step (#610) — always present when `input.sbom`/`input.componentBom` was supplied, `undefined` when neither was (nothing to attach, attach step skipped entirely). */
|
|
95
|
-
export interface ReferrerAttachResult {
|
|
96
|
-
/** True once every requested attach (`sbom`, `componentBom`) succeeded. `false` if `oras` was unavailable or any `oras attach` invocation failed. */
|
|
97
|
-
attached: boolean;
|
|
98
|
-
/** Human-readable reason `attached` is `false` (e.g. "oras is not installed"), omitted when `attached` is `true`. */
|
|
99
|
-
reason?: string;
|
|
100
|
-
}
|
|
101
|
-
export interface PublishImageOutput {
|
|
102
|
-
/** Content-addressed digest of the promoted image (`sha256:...`) — what the apply step references. */
|
|
103
|
-
digest: string;
|
|
104
|
-
/** Image reference the apply step can pull/run: `registry/repo@sha256:...` for `publish-image`, a host-local reference for `load-image-on-host`. */
|
|
105
|
-
uri: string;
|
|
106
|
-
/** #610: outcome of the best-effort SBOM/component-BOM referrer attach, when `input.sbom`/`input.componentBom` was supplied. `undefined` for `load-image-on-host` (no attach concept — registry-less) and for `publish-image` calls that supplied neither. */
|
|
107
|
-
referrerAttach?: ReferrerAttachResult;
|
|
108
|
-
}
|
|
58
|
+
export declare function createEcrRegistryBackend(executor?: CloudExecutor): RegistryLoginBackend;
|
|
59
|
+
/** The ECR backend the aws plugin contributes, over the real `CloudExecutor`. */
|
|
60
|
+
export declare const ecrRegistryBackend: RegistryLoginBackend;
|
|
109
61
|
/**
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
*/
|
|
115
|
-
export type PublishImageBackend = Capability<PublishImageInput, PublishImageOutput>;
|
|
116
|
-
/**
|
|
117
|
-
* Promote a built image from the archive into the environment's container
|
|
118
|
-
* registry: `docker load` the archived tarball, tag it for `to` (the env
|
|
119
|
-
* registry), `aws ecr get-login-password | docker login`, then `docker push`.
|
|
120
|
-
* Returns the pushed image's registry digest — what `cfn-deploy`/
|
|
121
|
-
* `ecs-update-service` reference via `imageRef: "@Publish.digest"`. No
|
|
122
|
-
* rollback: an already-pushed, still-valid image in the registry is not
|
|
123
|
-
* itself a problem to compensate (immutable, content-addressed, and simply
|
|
124
|
-
* unreferenced if a later step fails) — the opt-out this capability takes.
|
|
125
|
-
*
|
|
126
|
-
* #610: when `input.sbom` and/or `input.componentBom` are supplied, also
|
|
127
|
-
* attaches them as OCI referrers on the pushed digest via `oras attach` (see
|
|
128
|
-
* `attachReferrers` above) — best-effort, guarded on `oras` availability,
|
|
129
|
-
* surfaced on the output's `referrerAttach` rather than failing the publish.
|
|
62
|
+
* `publish-image` with ECR as its only login backend: core's verb, bound to
|
|
63
|
+
* this executor. Kept so aws-only callers and tests build it the way they
|
|
64
|
+
* always did; behaviour is unchanged (load, tag, ECR login, push, optional
|
|
65
|
+
* referrer attach).
|
|
130
66
|
*/
|
|
131
67
|
export declare function createPublishImageCapability(executor?: CloudExecutor, processRunner?: ProcessRunner): PublishImageBackend;
|
|
132
|
-
/**
|
|
68
|
+
/** `publish-image` bound to the real executor; the registered verb is core's, with this lexicon's ECR backend injected. */
|
|
133
69
|
export declare const publishImageCapability: PublishImageBackend;
|
|
134
70
|
/**
|
|
135
71
|
* Copy the image tarball straight onto a host and `docker load` it there —
|
|
@@ -167,28 +103,23 @@ export type PublishImageBackendKind = "publish-image" | "load-image-on-host";
|
|
|
167
103
|
* backends built above.
|
|
168
104
|
*/
|
|
169
105
|
export declare function selectPublishBackend(kind: PublishImageBackendKind, backends?: Partial<Record<PublishImageBackendKind, PublishImageBackend>>): PublishImageBackend;
|
|
170
|
-
export
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
export
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
/** Content hash of the published artifact. */
|
|
180
|
-
digest: string;
|
|
181
|
-
}
|
|
182
|
-
/** Promote a non-image artifact (jar, zip, arbitrary asset) from the archive to S3/CodeArtifact. */
|
|
106
|
+
export type { PublishArtifactInput, PublishArtifactOutput } from "@intentius/chant/components/verbs/publish-artifact";
|
|
107
|
+
/**
|
|
108
|
+
* The aws lexicon's storage backend for core's `publish-artifact`: `aws s3 cp`
|
|
109
|
+
* (endpoint-aware through the `CloudExecutor`). Core owns the digest and the
|
|
110
|
+
* object URI; this only uploads.
|
|
111
|
+
*/
|
|
112
|
+
export declare function createS3StorageBackend(executor?: CloudExecutor): ArtifactStorageBackend;
|
|
113
|
+
/** The S3 backend the aws plugin contributes, over the real `CloudExecutor`. */
|
|
114
|
+
export declare const s3StorageBackend: ArtifactStorageBackend;
|
|
183
115
|
/**
|
|
184
|
-
*
|
|
185
|
-
*
|
|
186
|
-
*
|
|
187
|
-
* the exact bytes uploaded.
|
|
116
|
+
* `publish-artifact` with S3 as its only storage backend: core's verb, bound
|
|
117
|
+
* to this executor. Kept so aws-only callers and tests build it the way they
|
|
118
|
+
* always did; behaviour is unchanged (upload, return uri + content digest).
|
|
188
119
|
*/
|
|
189
120
|
export declare function createPublishArtifactCapability(executor?: CloudExecutor): Capability<PublishArtifactInput, PublishArtifactOutput>;
|
|
190
|
-
/** Default `publish-artifact
|
|
121
|
+
/** Default `publish-artifact`, bound to the real executor; the registered verb is core's, with this lexicon's S3 backend injected. */
|
|
191
122
|
export declare const publishArtifactCapability: Capability<PublishArtifactInput, PublishArtifactOutput>;
|
|
192
|
-
/** Alias for `publish-artifact
|
|
123
|
+
/** Alias for `publish-artifact`: same capability, the docs/epic use both names for the same verb. */
|
|
193
124
|
export declare const publishAssetCapability: Capability<PublishArtifactInput, PublishArtifactOutput>;
|
|
194
125
|
//# sourceMappingURL=publish.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"publish.d.ts","sourceRoot":"","sources":["../../src/components/publish.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wCAAwC,CAAC;
|
|
1
|
+
{"version":3,"file":"publish.d.ts","sourceRoot":"","sources":["../../src/components/publish.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wCAAwC,CAAC;AACzE,OAAO,EAAwB,KAAK,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAE5E,OAAO,EAAwB,KAAK,aAAa,EAAE,MAAM,kDAAkD,CAAC;AAC5G,OAAO,EAEL,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EAC1B,MAAM,iDAAiD,CAAC;AAEzD,OAAO,EAEL,KAAK,sBAAsB,EAC3B,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,EAC3B,MAAM,oDAAoD,CAAC;AAI5D,YAAY,EACV,iBAAiB,EACjB,kBAAkB,EAClB,mBAAmB,EACnB,oBAAoB,GACrB,MAAM,iDAAiD,CAAC;AAIzD;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,CAAC,EAAE,aAAa,GAAG,oBAAoB,CAOvF;AAED,iFAAiF;AACjF,eAAO,MAAM,kBAAkB,EAAE,oBAAiD,CAAC;AAEnF;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAC1C,QAAQ,GAAE,aAAsC,EAChD,aAAa,GAAE,aAAsC,GACpD,mBAAmB,CAErB;AAED,2HAA2H;AAC3H,eAAO,MAAM,sBAAsB,EAAE,mBAAoD,CAAC;AAU1F;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,+BAA+B,CAC7C,QAAQ,GAAE,aAAsC,GAC/C,mBAAmB,CAYrB;AAED,mFAAmF;AACnF,eAAO,MAAM,yBAAyB,EAAE,mBAAuD,CAAC;AAIhG,wGAAwG;AACxG,MAAM,MAAM,uBAAuB,GAAG,eAAe,GAAG,oBAAoB,CAAC;AAE7E;;;;;;;;;;;;;GAaG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,uBAAuB,EAC7B,QAAQ,GAAE,OAAO,CAAC,MAAM,CAAC,uBAAuB,EAAE,mBAAmB,CAAC,CAGrE,GACA,mBAAmB,CAQrB;AAID,YAAY,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,oDAAoD,CAAC;AAEtH;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,CAAC,EAAE,aAAa,GAAG,sBAAsB,CAOvF;AAED,gFAAgF;AAChF,eAAO,MAAM,gBAAgB,EAAE,sBAAiD,CAAC;AAEjF;;;;GAIG;AACH,wBAAgB,+BAA+B,CAC7C,QAAQ,GAAE,aAAsC,GAC/C,UAAU,CAAC,oBAAoB,EAAE,qBAAqB,CAAC,CAEzD;AAED,sIAAsI;AACtI,eAAO,MAAM,yBAAyB,EAAE,UAAU,CAAC,oBAAoB,EAAE,qBAAqB,CAC3D,CAAC;AAEpC,qGAAqG;AACrG,eAAO,MAAM,sBAAsB,yDAA4B,CAAC"}
|
|
@@ -44,107 +44,37 @@
|
|
|
44
44
|
* image is already successfully promoted by the time this step runs — the
|
|
45
45
|
* one part of this capability that is genuinely best-effort.
|
|
46
46
|
*/
|
|
47
|
-
import { readFileSync } from "node:fs";
|
|
48
|
-
import { createHash } from "node:crypto";
|
|
49
47
|
import { defaultCloudExecutor } from "./cloud-executor.js";
|
|
50
48
|
import { archiveRelativePath } from "@intentius/chant/components/verbs/build-archive";
|
|
51
|
-
import { defaultProcessRunner
|
|
52
|
-
|
|
49
|
+
import { defaultProcessRunner } from "@intentius/chant/components/verbs/process-runner";
|
|
50
|
+
import { createPublishImageCapability as createCorePublishImage, } from "@intentius/chant/components/verbs/publish-image";
|
|
51
|
+
import { createPublishArtifactCapability as createCorePublishArtifact, } from "@intentius/chant/components/verbs/publish-artifact";
|
|
52
|
+
// ── publish-image: the ECR backend (the verb itself is core's) ──────────────
|
|
53
53
|
/**
|
|
54
|
-
*
|
|
55
|
-
* `
|
|
56
|
-
*
|
|
57
|
-
* `runner`. Never throws — a failure here is reported back to the caller as
|
|
58
|
-
* `{ ok: false, reason }` so a missing/erroring `oras` never fails the
|
|
59
|
-
* publish itself (see `attachReferrers`'s doc comment for why).
|
|
54
|
+
* The aws lexicon's registry login for core's `publish-image` (#3142, #3143):
|
|
55
|
+
* `aws ecr get-login-password | docker login`. The aws plugin contributes it;
|
|
56
|
+
* core owns load, tag, push and the digest read-back.
|
|
60
57
|
*/
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
}
|
|
69
|
-
catch (err) {
|
|
70
|
-
return { ok: false, reason: err instanceof Error ? err.message : String(err) };
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* Best-effort OCI-referrer attach for a just-pushed image (#610): attaches
|
|
75
|
-
* `input.sbom` and/or `input.componentBom`, when supplied, to `imageRef` via
|
|
76
|
-
* `oras attach`. Guarded on `oras` availability — a missing binary is
|
|
77
|
-
* reported back as `{ attached: false, reason }` rather than thrown, since
|
|
78
|
-
* the image itself is already successfully promoted by the time this step
|
|
79
|
-
* runs (attach is additive registry-side convenience on top of the
|
|
80
|
-
* archive-carried copy, per this module's doc comment, never a condition the
|
|
81
|
-
* core promote-by-digest job depends on). Returns `undefined` when neither
|
|
82
|
-
* `input.sbom` nor `input.componentBom` was supplied — nothing to attach,
|
|
83
|
-
* skipped entirely, no `oras` call at all.
|
|
84
|
-
*/
|
|
85
|
-
async function attachReferrers(runner, imageRef, input) {
|
|
86
|
-
if (!input.sbom && !input.componentBom)
|
|
87
|
-
return undefined;
|
|
88
|
-
if (!(await runner.available("oras"))) {
|
|
89
|
-
return { attached: false, reason: `"oras" is not installed or not on PATH — required to attach OCI referrers` };
|
|
90
|
-
}
|
|
91
|
-
const results = [];
|
|
92
|
-
if (input.sbom)
|
|
93
|
-
results.push(await attachOneReferrer(runner, imageRef, input.sbom, "sbom"));
|
|
94
|
-
if (input.componentBom)
|
|
95
|
-
results.push(await attachOneReferrer(runner, imageRef, input.componentBom, "component-bom"));
|
|
96
|
-
const failed = results.find((r) => !r.ok);
|
|
97
|
-
return failed ? { attached: false, reason: failed.reason } : { attached: true };
|
|
58
|
+
export function createEcrRegistryBackend(executor) {
|
|
59
|
+
return {
|
|
60
|
+
name: "ecr",
|
|
61
|
+
matches: (registry) => /\.dkr\.ecr(-fips)?\.[a-z0-9-]+\.amazonaws\.com(\.cn)?$/.test(registry),
|
|
62
|
+
// The real executor is built on first login, so loading the plugin shells out to nothing.
|
|
63
|
+
login: (registry) => (executor ?? defaultCloudExecutor()).ecr.login(registry),
|
|
64
|
+
};
|
|
98
65
|
}
|
|
66
|
+
/** The ECR backend the aws plugin contributes, over the real `CloudExecutor`. */
|
|
67
|
+
export const ecrRegistryBackend = createEcrRegistryBackend();
|
|
99
68
|
/**
|
|
100
|
-
*
|
|
101
|
-
*
|
|
102
|
-
*
|
|
103
|
-
*
|
|
104
|
-
* `ecs-update-service` reference via `imageRef: "@Publish.digest"`. No
|
|
105
|
-
* rollback: an already-pushed, still-valid image in the registry is not
|
|
106
|
-
* itself a problem to compensate (immutable, content-addressed, and simply
|
|
107
|
-
* unreferenced if a later step fails) — the opt-out this capability takes.
|
|
108
|
-
*
|
|
109
|
-
* #610: when `input.sbom` and/or `input.componentBom` are supplied, also
|
|
110
|
-
* attaches them as OCI referrers on the pushed digest via `oras attach` (see
|
|
111
|
-
* `attachReferrers` above) — best-effort, guarded on `oras` availability,
|
|
112
|
-
* surfaced on the output's `referrerAttach` rather than failing the publish.
|
|
69
|
+
* `publish-image` with ECR as its only login backend: core's verb, bound to
|
|
70
|
+
* this executor. Kept so aws-only callers and tests build it the way they
|
|
71
|
+
* always did; behaviour is unchanged (load, tag, ECR login, push, optional
|
|
72
|
+
* referrer attach).
|
|
113
73
|
*/
|
|
114
74
|
export function createPublishImageCapability(executor = defaultCloudExecutor(), processRunner = defaultProcessRunner()) {
|
|
115
|
-
return {
|
|
116
|
-
kind: "publish-image",
|
|
117
|
-
async run(_ctx, input) {
|
|
118
|
-
if (!input.to)
|
|
119
|
-
throw new Error(`publish-image "${input.from}": "to" (destination registry) is required`);
|
|
120
|
-
// `docker load` reports the archived image's local reference — a name:tag
|
|
121
|
-
// for a tagged build, or an image id. It's a valid `docker tag` source but
|
|
122
|
-
// never a registry digest, so the promoted digest is read back from the
|
|
123
|
-
// push below, not constructed from this.
|
|
124
|
-
const { digest: localRef } = await executor.docker.load({ inFile: archiveRelativePath(input.from) });
|
|
125
|
-
const repo = input.to.replace(/\/+$/, "");
|
|
126
|
-
// Publish under a tag: docker can neither tag nor push a digest-qualified
|
|
127
|
-
// reference (`repo@sha256:...`), so the transport is a tag and the stable
|
|
128
|
-
// identifier is the digest the push returns.
|
|
129
|
-
const pushRef = `${repo}:latest`;
|
|
130
|
-
await executor.docker.tag({ source: localRef, target: pushRef });
|
|
131
|
-
const registry = repo.split("/")[0];
|
|
132
|
-
await executor.ecr.login(registry);
|
|
133
|
-
const { digest: pushed } = await executor.docker.push({ image: pushRef });
|
|
134
|
-
// Normalize to a bare `sha256:...`, whether the client returned that or a
|
|
135
|
-
// full `repo@sha256:...` RepoDigest.
|
|
136
|
-
const digest = pushed.includes("@") ? pushed.slice(pushed.indexOf("@") + 1) : pushed;
|
|
137
|
-
for (const tag of input.tags ?? []) {
|
|
138
|
-
const tagged = `${repo}:${tag}`;
|
|
139
|
-
await executor.docker.tag({ source: localRef, target: tagged });
|
|
140
|
-
await executor.docker.push({ image: tagged });
|
|
141
|
-
}
|
|
142
|
-
const referrerAttach = await attachReferrers(processRunner, `${repo}@${digest}`, input);
|
|
143
|
-
return { digest, uri: `${repo}@${digest}`, ...(referrerAttach ? { referrerAttach } : {}) };
|
|
144
|
-
},
|
|
145
|
-
};
|
|
75
|
+
return createCorePublishImage({ docker: executor.docker, processRunner, backends: [createEcrRegistryBackend(executor)] });
|
|
146
76
|
}
|
|
147
|
-
/**
|
|
77
|
+
/** `publish-image` bound to the real executor; the registered verb is core's, with this lexicon's ECR backend injected. */
|
|
148
78
|
export const publishImageCapability = createPublishImageCapability();
|
|
149
79
|
// ── load-image-on-host (host backend) ───────────────────────────────────────
|
|
150
80
|
/** Default on-host tarball destination when `hostPath` is omitted, derived from the archive path's basename. */
|
|
@@ -208,27 +138,30 @@ export function selectPublishBackend(kind, backends = {
|
|
|
208
138
|
}
|
|
209
139
|
return backend;
|
|
210
140
|
}
|
|
211
|
-
/** Promote a non-image artifact (jar, zip, arbitrary asset) from the archive to S3/CodeArtifact. */
|
|
212
141
|
/**
|
|
213
|
-
*
|
|
214
|
-
* (endpoint-aware through the `CloudExecutor`).
|
|
215
|
-
*
|
|
216
|
-
* the exact bytes uploaded.
|
|
142
|
+
* The aws lexicon's storage backend for core's `publish-artifact`: `aws s3 cp`
|
|
143
|
+
* (endpoint-aware through the `CloudExecutor`). Core owns the digest and the
|
|
144
|
+
* object URI; this only uploads.
|
|
217
145
|
*/
|
|
218
|
-
export function
|
|
146
|
+
export function createS3StorageBackend(executor) {
|
|
219
147
|
return {
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
const basename = localPath.split("/").pop() ?? localPath;
|
|
225
|
-
const uri = input.to.endsWith("/") ? `${input.to}${basename}` : input.to;
|
|
226
|
-
await executor.s3.cp({ from: localPath, to: uri });
|
|
227
|
-
return { uri, digest };
|
|
228
|
-
},
|
|
148
|
+
name: "s3",
|
|
149
|
+
matches: (uri) => uri.startsWith("s3://"),
|
|
150
|
+
// The real executor is built on first upload, so loading the plugin shells out to nothing.
|
|
151
|
+
upload: (args) => (executor ?? defaultCloudExecutor()).s3.cp(args),
|
|
229
152
|
};
|
|
230
153
|
}
|
|
231
|
-
/**
|
|
154
|
+
/** The S3 backend the aws plugin contributes, over the real `CloudExecutor`. */
|
|
155
|
+
export const s3StorageBackend = createS3StorageBackend();
|
|
156
|
+
/**
|
|
157
|
+
* `publish-artifact` with S3 as its only storage backend: core's verb, bound
|
|
158
|
+
* to this executor. Kept so aws-only callers and tests build it the way they
|
|
159
|
+
* always did; behaviour is unchanged (upload, return uri + content digest).
|
|
160
|
+
*/
|
|
161
|
+
export function createPublishArtifactCapability(executor = defaultCloudExecutor()) {
|
|
162
|
+
return createCorePublishArtifact({ backends: [createS3StorageBackend(executor)] });
|
|
163
|
+
}
|
|
164
|
+
/** Default `publish-artifact`, bound to the real executor; the registered verb is core's, with this lexicon's S3 backend injected. */
|
|
232
165
|
export const publishArtifactCapability = createPublishArtifactCapability();
|
|
233
|
-
/** Alias for `publish-artifact
|
|
166
|
+
/** Alias for `publish-artifact`: same capability, the docs/epic use both names for the same verb. */
|
|
234
167
|
export const publishAssetCapability = publishArtifactCapability;
|
package/dist/integrity.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"algorithm": "sha256",
|
|
3
3
|
"artifacts": {
|
|
4
|
-
"manifest.json": "
|
|
4
|
+
"manifest.json": "6d63402ac557c9c432818176908605ad1bd86ba72ce417b50aa3f283ed473620",
|
|
5
5
|
"meta.json": "6f48557ed4203cbdeafdb47e7270fdf3533f6d6e6189987246301ed8e72170e9",
|
|
6
6
|
"types/index.d.ts": "8651f9ae166668f4311eea1fe61c3fe235f345947951c1d23d1df24a4fd3384f",
|
|
7
7
|
"rules/hardcoded-region.ts": "957eadcaa9f39cc17d21437565d7a94607d9b082cf28918b178fa067f07498a9",
|
|
@@ -75,5 +75,5 @@
|
|
|
75
75
|
"skills/chant-aws-eks.md": "8789255709ff004ad0a875fd5999edcdc66fc6e33d710db058d9f42703bcfdfe",
|
|
76
76
|
"skills/chant-aws-carve-terraform.md": "8780b94ce60aded935938d5ef20ea667738354051da1bf9ca6d70d9886f65d21"
|
|
77
77
|
},
|
|
78
|
-
"composite": "
|
|
78
|
+
"composite": "5425340cfa33d03f1d5772e1819704c43dd9c0524249be73bdb021716b180719"
|
|
79
79
|
}
|
package/dist/manifest.json
CHANGED
package/dist/plugin.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAqQ,MAAM,0BAA0B,CAAC;AAwCjU;yEACyE;AACzE,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAiBnD,eAAO,MAAM,SAAS,EAAE,aAgkCvB,CAAC"}
|
package/dist/plugin.js
CHANGED
|
@@ -2,6 +2,7 @@ import { compositeCatalog } from "./composites/catalog.js";
|
|
|
2
2
|
import { createRequire } from "module";
|
|
3
3
|
import { awsBehaviourKinds } from "./behaviour-kinds.js";
|
|
4
4
|
import { detectTemplate } from "./detect.js";
|
|
5
|
+
import { awsCapabilityPack } from "./capabilities/pack.js";
|
|
5
6
|
const require = createRequire(moduleSourceUrl(import.meta.url));
|
|
6
7
|
import { discoverLintRules } from "@intentius/chant/lint/discover";
|
|
7
8
|
import { postSynthChecks as postSynthCheckList } from "./lint/post-synth/index.js";
|
|
@@ -63,6 +64,7 @@ export const awsPlugin = {
|
|
|
63
64
|
auditCatalog: () => awsAuditCatalog,
|
|
64
65
|
// Live edge reconstruction for `chant graph --live` (#778).
|
|
65
66
|
referenceCatalog: awsReferenceCatalog,
|
|
67
|
+
capabilityPack: awsCapabilityPack,
|
|
66
68
|
lintRules() {
|
|
67
69
|
const rulesDir = join(dirname(fileURLToPath(import.meta.url)), "lint", "rules");
|
|
68
70
|
return discoverLintRules(rulesDir, import.meta.url);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@intentius/chant-lexicon-aws",
|
|
3
|
-
"version": "0.124.
|
|
3
|
+
"version": "0.124.48",
|
|
4
4
|
"description": "AWS CloudFormation lexicon for chant — declarative IaC in TypeScript",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://intentius.io/chant",
|
|
@@ -80,6 +80,6 @@
|
|
|
80
80
|
"typescript": "^5.9.3"
|
|
81
81
|
},
|
|
82
82
|
"peerDependencies": {
|
|
83
|
-
"@intentius/chant": "^0.124.
|
|
83
|
+
"@intentius/chant": "^0.124.48"
|
|
84
84
|
}
|
|
85
85
|
}
|