@intentius/chant-lexicon-aws 0.124.31 → 0.124.32
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/actions/dynamodb.js +41 -0
- package/dist/actions/ecr.js +9 -0
- package/dist/actions/ecs.js +5 -0
- package/dist/actions/iam.js +3 -0
- package/dist/actions/index.js +9 -0
- package/dist/actions/lambda.js +11 -0
- package/dist/actions/logs.js +4 -0
- package/dist/actions/s3.js +40 -0
- package/dist/actions/sns.js +5 -0
- package/dist/actions/sqs.js +15 -0
- package/dist/agentcore/trace-fetch.d.ts.map +1 -1
- package/dist/agentcore/trace-fetch.js +472 -0
- package/dist/agentcore/trace-render.js +359 -0
- package/dist/ambient.js +148 -0
- package/dist/api/credential-chain.d.ts +30 -3
- package/dist/api/credential-chain.d.ts.map +1 -1
- package/dist/api/credential-chain.js +509 -0
- package/dist/api/read-client.d.ts +16 -43
- package/dist/api/read-client.d.ts.map +1 -1
- package/dist/api/read-client.js +458 -0
- package/dist/api/sigv4.d.ts +4 -4
- package/dist/api/sigv4.js +185 -0
- package/dist/behaviour-kinds.js +114 -0
- package/dist/caller-identity.d.ts +3 -5
- package/dist/caller-identity.d.ts.map +1 -1
- package/dist/caller-identity.js +146 -0
- package/dist/codegen/docs-cli.js +2 -0
- package/dist/codegen/docs.js +120 -0
- package/dist/codegen/enum-overlay.js +162 -0
- package/dist/codegen/extensions.js +139 -0
- package/dist/codegen/fallback.js +32 -0
- package/dist/codegen/generate-cli.js +15 -0
- package/dist/codegen/generate-lexicon.js +70 -0
- package/dist/codegen/generate-typescript.js +226 -0
- package/dist/codegen/generate.d.ts.map +1 -1
- package/dist/codegen/generate.js +234 -0
- package/dist/codegen/naming.js +135 -0
- package/dist/codegen/package.js +67 -0
- package/dist/codegen/patches.d.ts +26 -1
- package/dist/codegen/patches.d.ts.map +1 -1
- package/dist/codegen/patches.js +90 -0
- package/dist/codegen/property-overlay.js +85 -0
- package/dist/codegen/property-overlay.json +1 -16
- package/dist/codegen/sam.js +402 -0
- package/dist/codegen/typecheck.js +4 -0
- package/dist/codegen/versions.js +31 -0
- package/dist/components/__tests__/mock-cloud-executor.js +326 -0
- package/dist/components/apply.d.ts +44 -1
- package/dist/components/apply.d.ts.map +1 -1
- package/dist/components/apply.js +752 -0
- package/dist/components/builders.js +37 -0
- package/dist/components/capability-plugin.js +66 -0
- package/dist/components/cloud-executor.d.ts +35 -0
- package/dist/components/cloud-executor.d.ts.map +1 -1
- package/dist/components/cloud-executor.js +576 -0
- package/dist/components/config-bom.js +207 -0
- package/dist/components/host-delivery.js +117 -0
- package/dist/components/index.js +18 -0
- package/dist/components/job-submission.js +77 -0
- package/dist/components/publish.js +234 -0
- package/dist/components/safety.js +62 -0
- package/dist/components/wait-aws.js +68 -0
- package/dist/composites/agentcore-agent.js +187 -0
- package/dist/composites/agentcore-trust-policy.js +13 -0
- package/dist/composites/alb-shared.js +84 -0
- package/dist/composites/bucket-deployment.js +93 -0
- package/dist/composites/catalog.js +2714 -0
- package/dist/composites/dynamodb-table.js +66 -0
- package/dist/composites/ec2-instance-bundle.js +75 -0
- package/dist/composites/ec2-instance-role.js +26 -0
- package/dist/composites/ecr-repository.js +64 -0
- package/dist/composites/ecs-trust-policy.js +10 -0
- package/dist/composites/efs-with-access-point.js +44 -0
- package/dist/composites/eks-cluster.js +118 -0
- package/dist/composites/fargate-alb.js +216 -0
- package/dist/composites/fargate-service.js +222 -0
- package/dist/composites/index.js +28 -0
- package/dist/composites/lambda-api.js +15 -0
- package/dist/composites/lambda-dynamodb.js +77 -0
- package/dist/composites/lambda-eventbridge.js +27 -0
- package/dist/composites/lambda-function.js +54 -0
- package/dist/composites/lambda-s3.js +93 -0
- package/dist/composites/lambda-sns.js +23 -0
- package/dist/composites/lambda-sqs.js +34 -0
- package/dist/composites/landing-zone.js +82 -0
- package/dist/composites/microvm-app.js +293 -0
- package/dist/composites/minimal-vpc.js +40 -0
- package/dist/composites/monitoring-stack.js +105 -0
- package/dist/composites/nlb-service.js +61 -0
- package/dist/composites/rds-instance.js +98 -0
- package/dist/composites/scheduled-lambda.js +28 -0
- package/dist/composites/solr-fargate-service.js +33 -0
- package/dist/composites/step-functions-workflow.js +78 -0
- package/dist/composites/vpc-default.js +132 -0
- package/dist/condition.js +43 -0
- package/dist/coverage.js +4 -0
- package/dist/deep-observe.d.ts.map +1 -1
- package/dist/deep-observe.js +709 -0
- package/dist/deep-topology.js +226 -0
- package/dist/default-tags.js +50 -0
- package/dist/defaults.js +85 -0
- package/dist/dependencies.js +269 -0
- package/dist/detect.js +21 -0
- package/dist/disruption.d.ts.map +1 -1
- package/dist/disruption.js +129 -0
- package/dist/effect-receipt-row.js +107 -0
- package/dist/generated/index.d.ts +1297 -82
- package/dist/generated/index.d.ts.map +1 -1
- package/dist/generated/index.js +12382 -0
- package/dist/generated/runtime.js +4 -0
- package/dist/governance.js +131 -0
- package/dist/identity-observe.d.ts.map +1 -1
- package/dist/identity-observe.js +127 -0
- package/dist/import/generator.js +757 -0
- package/dist/import/live-export.js +34 -0
- package/dist/import/parser.js +394 -0
- package/dist/index.js +69 -0
- package/dist/integrity.json +6 -6
- package/dist/intrinsics.js +393 -0
- package/dist/lint/audit-catalog.js +87 -0
- package/dist/lint/audit-lineage.js +150 -0
- package/dist/lint/post-synth/cf-refs.js +247 -0
- package/dist/lint/post-synth/cor020.js +60 -0
- package/dist/lint/post-synth/ext001.d.ts.map +1 -1
- package/dist/lint/post-synth/ext001.js +197 -0
- package/dist/lint/post-synth/index.js +124 -0
- package/dist/lint/post-synth/waw010.js +41 -0
- package/dist/lint/post-synth/waw011.js +41 -0
- package/dist/lint/post-synth/waw013.js +38 -0
- package/dist/lint/post-synth/waw014.js +42 -0
- package/dist/lint/post-synth/waw015.js +88 -0
- package/dist/lint/post-synth/waw016.d.ts.map +1 -1
- package/dist/lint/post-synth/waw016.js +116 -0
- package/dist/lint/post-synth/waw017.js +43 -0
- package/dist/lint/post-synth/waw018.js +61 -0
- package/dist/lint/post-synth/waw019.js +64 -0
- package/dist/lint/post-synth/waw020.js +56 -0
- package/dist/lint/post-synth/waw021.js +44 -0
- package/dist/lint/post-synth/waw022.js +36 -0
- package/dist/lint/post-synth/waw023.js +40 -0
- package/dist/lint/post-synth/waw024.js +46 -0
- package/dist/lint/post-synth/waw025.js +36 -0
- package/dist/lint/post-synth/waw026.js +38 -0
- package/dist/lint/post-synth/waw027.js +41 -0
- package/dist/lint/post-synth/waw028.js +39 -0
- package/dist/lint/post-synth/waw029.js +54 -0
- package/dist/lint/post-synth/waw030.js +282 -0
- package/dist/lint/post-synth/waw031.js +58 -0
- package/dist/lint/post-synth/waw032.js +45 -0
- package/dist/lint/post-synth/waw033.js +75 -0
- package/dist/lint/post-synth/waw034.js +52 -0
- package/dist/lint/post-synth/waw035.js +56 -0
- package/dist/lint/post-synth/waw036.js +79 -0
- package/dist/lint/post-synth/waw037.js +67 -0
- package/dist/lint/post-synth/waw038.js +42 -0
- package/dist/lint/post-synth/waw039.js +42 -0
- package/dist/lint/post-synth/waw040.js +45 -0
- package/dist/lint/post-synth/waw041.js +40 -0
- package/dist/lint/post-synth/waw042.js +99 -0
- package/dist/lint/post-synth/waw043.js +51 -0
- package/dist/lint/post-synth/waw044.js +64 -0
- package/dist/lint/post-synth/waw045.js +49 -0
- package/dist/lint/post-synth/waw046.js +52 -0
- package/dist/lint/post-synth/waw047.js +43 -0
- package/dist/lint/post-synth/waw048.js +40 -0
- package/dist/lint/post-synth/waw049.js +78 -0
- package/dist/lint/post-synth/waw050.js +44 -0
- package/dist/lint/post-synth/waw051.js +41 -0
- package/dist/lint/post-synth/waw052.js +43 -0
- package/dist/lint/post-synth/waw053.js +43 -0
- package/dist/lint/post-synth/waw054.js +41 -0
- package/dist/lint/post-synth/waw055.js +41 -0
- package/dist/lint/post-synth/waw056.js +65 -0
- package/dist/lint/post-synth/waw057.js +43 -0
- package/dist/lint/post-synth/waw058.js +61 -0
- package/dist/lint/post-synth/waw059.js +338 -0
- package/dist/lint/post-synth/waw060.js +83 -0
- package/dist/lint/post-synth/waw061.js +60 -0
- package/dist/lint/post-synth/waw062.js +0 -0
- package/dist/lint/post-synth/waw063.js +0 -0
- package/dist/lint/post-synth/waw064.js +45 -0
- package/dist/lint/post-synth/waw065.js +104 -0
- package/dist/lint/post-synth/waw066.js +145 -0
- package/dist/lint/post-synth/waw067.js +115 -0
- package/dist/lint/post-synth/waw068.js +69 -0
- package/dist/lint/post-synth/waw069.js +0 -0
- package/dist/lint/rules/hardcoded-region.js +38 -0
- package/dist/lint/rules/iam-wildcard.js +60 -0
- package/dist/lint/rules/index.js +6 -0
- package/dist/lint/rules/s3-encryption.js +60 -0
- package/dist/live-attrs.js +42 -0
- package/dist/lsp/completions.d.ts.map +1 -1
- package/dist/lsp/completions.js +18 -0
- package/dist/lsp/hover.d.ts.map +1 -1
- package/dist/lsp/hover.js +66 -0
- package/dist/manifest.json +1 -1
- package/dist/mapping.js +33 -0
- package/dist/meta.json +17359 -784
- package/dist/nested-stack.js +95 -0
- package/dist/okf/index.md +203 -0
- package/dist/okf/rules/EXT001.md +1 -0
- package/dist/okf/rules/WAW016.md +2 -0
- package/dist/okf/rules/WAW019.md +1 -0
- package/dist/okf/rules/WAW028.md +1 -0
- package/dist/okf/rules/WAW030.md +2 -0
- package/dist/okf/rules/WAW039.md +1 -0
- package/dist/okf/rules/WAW049.md +1 -0
- package/dist/okf/rules/WAW056.md +1 -0
- package/dist/okf/rules/WAW058.md +1 -0
- package/dist/okf/rules/WAW062.md +1 -0
- package/dist/okf/rules/WAW064.md +1 -0
- package/dist/okf/rules/WAW065.md +1 -0
- package/dist/okf/rules/WAW066.md +1 -0
- package/dist/okf/rules/WAW067.md +1 -0
- package/dist/okf/rules/WAW068.md +1 -0
- package/dist/okf/rules/WAW069.md +4 -0
- package/dist/okf/types/AIWorkloadConfig.md +23 -0
- package/dist/okf/types/ARCRegionSwitchPlan.md +1 -0
- package/dist/okf/types/AccountAccessApplication.md +28 -0
- package/dist/okf/types/AccountAccessEntitlement.md +22 -0
- package/dist/okf/types/ActionTarget.md +20 -0
- package/dist/okf/types/AdConfiguration.md +21 -0
- package/dist/okf/types/Adapter.md +26 -0
- package/dist/okf/types/AgentContext.md +35 -0
- package/dist/okf/types/AgentGoal.md +31 -0
- package/dist/okf/types/AgentProfile.md +34 -0
- package/dist/okf/types/Alarm.md +3 -1
- package/dist/okf/types/AlarmModel.md +14 -9
- package/dist/okf/types/AmplifyWebhook.md +25 -0
- package/dist/okf/types/ApiCache.md +8 -8
- package/dist/okf/types/ApiGatewayManagedOverrides.md +5 -5
- package/dist/okf/types/AppAuthorization.md +35 -0
- package/dist/okf/types/AppBlockBuilder.md +1 -0
- package/dist/okf/types/AppInstance.md +2 -2
- package/dist/okf/types/AppInstanceBot.md +2 -2
- package/dist/okf/types/AppStreamFleet.md +3 -2
- package/dist/okf/types/AppSyncApiKey.md +6 -6
- package/dist/okf/types/AppSyncType.md +22 -0
- package/dist/okf/types/ApplicationStatusCheck.md +36 -0
- package/dist/okf/types/ApplicationVersion.md +4 -1
- package/dist/okf/types/ApplicationsList.md +26 -0
- package/dist/okf/types/ApprovalPolicy.md +28 -0
- package/dist/okf/types/ArchiveRule.md +24 -0
- package/dist/okf/types/Asset.md +30 -0
- package/dist/okf/types/Backup.md +31 -0
- package/dist/okf/types/BedrockAgentCoreDataset.md +1 -1
- package/dist/okf/types/BedrockAgentCoreGateway.md +3 -0
- package/dist/okf/types/BedrockSession.md +28 -0
- package/dist/okf/types/BillEstimate.md +35 -0
- package/dist/okf/types/Brand.md +32 -0
- package/dist/okf/types/CallAnalyticsCategory.md +25 -0
- package/dist/okf/types/Campaign.md +28 -0
- package/dist/okf/types/CapacityProvider.md +30 -0
- package/dist/okf/types/Case.md +24 -0
- package/dist/okf/types/CertificateAssociation.md +13 -0
- package/dist/okf/types/ChangeSet.md +36 -0
- package/dist/okf/types/ChannelFlow.md +29 -0
- package/dist/okf/types/ChimeChannel.md +39 -0
- package/dist/okf/types/Classifier.md +6 -6
- package/dist/okf/types/ClientVpnAuthorizationRule.md +6 -6
- package/dist/okf/types/ClientVpnEndpoint.md +2 -0
- package/dist/okf/types/ClientVpnRoute.md +5 -5
- package/dist/okf/types/CloudConnector.md +29 -0
- package/dist/okf/types/Cluster.md +39 -0
- package/dist/okf/types/ClusterSchedulerConfig.md +30 -0
- package/dist/okf/types/CodeCommitRepository.md +12 -12
- package/dist/okf/types/CodeConnectionsHost.md +26 -0
- package/dist/okf/types/CodeRepository.md +5 -5
- package/dist/okf/types/CompositeAlarm.md +1 -0
- package/dist/okf/types/ComputeEnvironment.md +2 -0
- package/dist/okf/types/ComputeNodeGroup.md +1 -1
- package/dist/okf/types/ComputeQuota.md +34 -0
- package/dist/okf/types/ConfigRule.md +1 -1
- package/dist/okf/types/ConfigurationRecorder.md +7 -6
- package/dist/okf/types/ConnectAttachment.md +2 -0
- package/dist/okf/types/ConnectQueue.md +5 -1
- package/dist/okf/types/ConnectVocabulary.md +28 -0
- package/dist/okf/types/ConnectionType.md +24 -0
- package/dist/okf/types/ConsentPortal.md +33 -0
- package/dist/okf/types/ContactMethod.md +29 -0
- package/dist/okf/types/ContainerAssociation.md +26 -0
- package/dist/okf/types/ContainerFleet.md +1 -1
- package/dist/okf/types/ContainerGroupDefinition.md +1 -1
- package/dist/okf/types/Content.md +40 -0
- package/dist/okf/types/ContentAssociation.md +28 -0
- package/dist/okf/types/CustomDetectionRuleAssociation.md +28 -0
- package/dist/okf/types/CustomEntityType.md +4 -9
- package/dist/okf/types/Customization.md +22 -0
- package/dist/okf/types/CwIntegration.md +31 -0
- package/dist/okf/types/DAXParameterGroup.md +3 -8
- package/dist/okf/types/DAXSubnetGroup.md +0 -5
- package/dist/okf/types/DBClusterEndpoint.md +31 -0
- package/dist/okf/types/DBProxyTargetGroup.md +1 -0
- package/dist/okf/types/DBSnapshot.md +62 -0
- package/dist/okf/types/DLMLifecyclePolicy.md +12 -12
- package/dist/okf/types/DLPSetting.md +31 -0
- package/dist/okf/types/DMSInstanceProfile.md +1 -1
- package/dist/okf/types/DRSLaunchConfigurationTemplate.md +28 -0
- package/dist/okf/types/Daemon.md +1 -0
- package/dist/okf/types/DataExchangeDataSet.md +29 -0
- package/dist/okf/types/DataIntegrationFlow.md +27 -0
- package/dist/okf/types/DataMigration.md +1 -1
- package/dist/okf/types/DataProvider.md +2 -1
- package/dist/okf/types/DataQualityRuleset.md +6 -11
- package/dist/okf/types/DataSource.md +23 -0
- package/dist/okf/types/Dataset.md +20 -0
- package/dist/okf/types/DatasetIntegration.md +23 -0
- package/dist/okf/types/DbCluster.md +1 -1
- package/dist/okf/types/DbInstance.md +8 -2
- package/dist/okf/types/DeadlineBudget.md +29 -0
- package/dist/okf/types/DelegationSet.md +23 -0
- package/dist/okf/types/DeliveryChannel.md +6 -11
- package/dist/okf/types/DevOpsAgentAgentSpace.md +4 -0
- package/dist/okf/types/DevOpsAgentService.md +1 -0
- package/dist/okf/types/DevOpsAgentTrigger.md +28 -0
- package/dist/okf/types/DirectConnectGatewayAttachment.md +2 -0
- package/dist/okf/types/Directory.md +60 -0
- package/dist/okf/types/DocDBDBClusterParameterGroup.md +5 -10
- package/dist/okf/types/DocDBDBSubnetGroup.md +4 -9
- package/dist/okf/types/DocDBElasticClusterSnapshot.md +36 -0
- package/dist/okf/types/DocumentClassifierEndpoint.md +27 -0
- package/dist/okf/types/Domain.md +27 -0
- package/dist/okf/types/EKSCertificateAuthority.md +42 -0
- package/dist/okf/types/EKSCluster.md +8 -0
- package/dist/okf/types/EcSnapshot.md +66 -0
- package/dist/okf/types/EmailIdentityCertificate.md +15 -0
- package/dist/okf/types/EndpointConfig.md +14 -13
- package/dist/okf/types/EntityRecognizer.md +27 -0
- package/dist/okf/types/EntityRecognizerEndpoint.md +31 -0
- package/dist/okf/types/EnvironmentEC2.md +13 -13
- package/dist/okf/types/EvaluationForm.md +1 -0
- package/dist/okf/types/Evaluator.md +6 -2
- package/dist/okf/types/EventAction.md +26 -0
- package/dist/okf/types/EventRule.md +2 -0
- package/dist/okf/types/EventSource.md +30 -0
- package/dist/okf/types/EventTracker.md +22 -0
- package/dist/okf/types/EventsV2EventBus.md +28 -0
- package/dist/okf/types/EventsV2ResourcePolicy.md +19 -0
- package/dist/okf/types/EventsV2Subscriber.md +39 -0
- package/dist/okf/types/ExperimentDefinition.md +39 -0
- package/dist/okf/types/ExperimentRun.md +33 -0
- package/dist/okf/types/ExperimentTrialComponent.md +13 -11
- package/dist/okf/types/FHIRDatastore.md +3 -0
- package/dist/okf/types/FSxSnapshot.md +5 -5
- package/dist/okf/types/FSxVolume.md +9 -9
- package/dist/okf/types/FeaturedResultsSet.md +26 -0
- package/dist/okf/types/Feed.md +1 -0
- package/dist/okf/types/FieldLevelEncryptionConfig.md +25 -0
- package/dist/okf/types/FieldLevelEncryptionProfile.md +22 -0
- package/dist/okf/types/FileCache.md +45 -0
- package/dist/okf/types/Filter.md +27 -0
- package/dist/okf/types/Firewall.md +6 -0
- package/dist/okf/types/FlowMediaStream.md +28 -0
- package/dist/okf/types/FlowOutput.md +1 -0
- package/dist/okf/types/FpgaImage.md +38 -0
- package/dist/okf/types/Function.md +2 -2
- package/dist/okf/types/Gateway.md +41 -0
- package/dist/okf/types/GatewayClusterAssociations.md +23 -0
- package/dist/okf/types/GatewayRateLimit.md +26 -0
- package/dist/okf/types/GatewayRule.md +32 -0
- package/dist/okf/types/GlobalReplicationGroup.md +3 -0
- package/dist/okf/types/GlobalResolver.md +1 -1
- package/dist/okf/types/GlobalTable.md +1 -0
- package/dist/okf/types/GlueConnection.md +5 -4
- package/dist/okf/types/GlueSecurityConfiguration.md +1 -6
- package/dist/okf/types/GlueSession.md +38 -0
- package/dist/okf/types/GlueTable.md +5 -10
- package/dist/okf/types/GlueWorkflow.md +5 -10
- package/dist/okf/types/Group.md +27 -0
- package/dist/okf/types/Harness.md +1 -0
- package/dist/okf/types/HostKey.md +33 -0
- package/dist/okf/types/HostedZone.md +1 -0
- package/dist/okf/types/HttpApi.md +2 -0
- package/dist/okf/types/HttpNamespace.md +5 -5
- package/dist/okf/types/HubV2.md +1 -0
- package/dist/okf/types/HumanTaskUi.md +22 -0
- package/dist/okf/types/IPv4Pool.md +28 -0
- package/dist/okf/types/ImageBuilder.md +1 -0
- package/dist/okf/types/ImageBuilderImage.md +1 -1
- package/dist/okf/types/ImagePipeline.md +1 -1
- package/dist/okf/types/InferenceComponent.md +5 -1
- package/dist/okf/types/InfluxDBBackup.md +65 -0
- package/dist/okf/types/InfluxDBCluster.md +3 -0
- package/dist/okf/types/InfrastructureConfiguration.md +2 -0
- package/dist/okf/types/IngestionDestination.md +28 -0
- package/dist/okf/types/InputSecurityGroup.md +6 -4
- package/dist/okf/types/InspectorV2Connector.md +38 -0
- package/dist/okf/types/InstanceEventWindow.md +25 -0
- package/dist/okf/types/InstanceFleetConfig.md +10 -10
- package/dist/okf/types/InstanceGroupConfig.md +3 -3
- package/dist/okf/types/InstrumentationConfig.md +31 -0
- package/dist/okf/types/IntegrationAssociation.md +3 -0
- package/dist/okf/types/IoTSiteWiseApplication.md +34 -0
- package/dist/okf/types/IoTSiteWiseDataset.md +5 -2
- package/dist/okf/types/IoTSiteWiseTask.md +24 -0
- package/dist/okf/types/IpamExternalResourceVerificationToken.md +35 -0
- package/dist/okf/types/IpamInternetRegistryAssociation.md +32 -0
- package/dist/okf/types/Job.md +35 -0
- package/dist/okf/types/JobTemplate.md +26 -0
- package/dist/okf/types/KinesisChannel.md +31 -0
- package/dist/okf/types/KinesisStream.md +1 -0
- package/dist/okf/types/LambdaResourcePolicy.md +14 -0
- package/dist/okf/types/Lexicon.md +34 -0
- package/dist/okf/types/LicenseAssetGroup.md +23 -0
- package/dist/okf/types/LicenseConfiguration.md +33 -0
- package/dist/okf/types/LicenseServerEndpoint.md +32 -0
- package/dist/okf/types/LightsailKeyPair.md +29 -0
- package/dist/okf/types/LimitsProfile.md +27 -0
- package/dist/okf/types/LocationAzureBlob.md +2 -1
- package/dist/okf/types/LocationObjectStorage.md +1 -0
- package/dist/okf/types/LogAlarm.md +2 -0
- package/dist/okf/types/MGNConnector.md +23 -0
- package/dist/okf/types/MGNLaunchConfigurationTemplate.md +37 -0
- package/dist/okf/types/MLTransform.md +15 -15
- package/dist/okf/types/MWAAServerlessWorkflow.md +3 -0
- package/dist/okf/types/ManagedNotificationAccountContactAssociation.md +1 -0
- package/dist/okf/types/ManagedNotificationAdditionalChannelAssociation.md +1 -0
- package/dist/okf/types/MediaConvertJobTemplate.md +11 -13
- package/dist/okf/types/MediaConvertQueue.md +8 -10
- package/dist/okf/types/MediaInsightsPipelineConfiguration.md +28 -0
- package/dist/okf/types/MediaLiveInput.md +41 -18
- package/dist/okf/types/MediaPackageV2Channel.md +3 -0
- package/dist/okf/types/MediaPackageV2OriginEndpoint.md +1 -0
- package/dist/okf/types/MediaPipelineKinesisVideoStreamPool.md +28 -0
- package/dist/okf/types/MediaTailorFunction.md +27 -0
- package/dist/okf/types/MedicalVocabulary.md +21 -0
- package/dist/okf/types/Member.md +26 -0
- package/dist/okf/types/Memory.md +6 -0
- package/dist/okf/types/MemoryDBSnapshot.md +29 -0
- package/dist/okf/types/Metric.md +59 -0
- package/dist/okf/types/MetricAttribution.md +23 -0
- package/dist/okf/types/MicrosoftAD.md +11 -11
- package/dist/okf/types/MigrationProject.md +8 -1
- package/dist/okf/types/Monitor.md +26 -0
- package/dist/okf/types/NFSFileShare.md +44 -0
- package/dist/okf/types/NeptuneGraphGraph.md +1 -0
- package/dist/okf/types/NetworkConnector.md +4 -0
- package/dist/okf/types/NetworkFlowMonitorScope.md +23 -0
- package/dist/okf/types/NetworkMigrationDefinition.md +31 -0
- package/dist/okf/types/NetworkSecurityManagerDeployment.md +31 -0
- package/dist/okf/types/NetworkSecurityManagerPolicy.md +32 -0
- package/dist/okf/types/NetworkSecurityManagerScope.md +29 -0
- package/dist/okf/types/NotebookInstance.md +18 -18
- package/dist/okf/types/NotebookInstanceLifecycleConfig.md +6 -5
- package/dist/okf/types/NotifyConfiguration.md +35 -0
- package/dist/okf/types/OTelEnrichment.md +2 -0
- package/dist/okf/types/OnlineEvaluationConfig.md +0 -1
- package/dist/okf/types/OrganizationConfigRule.md +7 -7
- package/dist/okf/types/Outpost.md +32 -0
- package/dist/okf/types/ParallelData.md +40 -0
- package/dist/okf/types/Partition.md +5 -5
- package/dist/okf/types/PaymentConnector.md +4 -1
- package/dist/okf/types/Pentest.md +1 -0
- package/dist/okf/types/PerfReports.md +28 -0
- package/dist/okf/types/PermissionAssociation.md +30 -0
- package/dist/okf/types/PersonalizeDataset.md +1 -0
- package/dist/okf/types/PersonalizeDatasetGroup.md +1 -0
- package/dist/okf/types/PersonalizeSchema.md +1 -0
- package/dist/okf/types/Pipeline.md +25 -0
- package/dist/okf/types/PlaybackConfiguration.md +1 -0
- package/dist/okf/types/PolicyAssociation.md +1 -1
- package/dist/okf/types/PolicyGrant.md +2 -2
- package/dist/okf/types/PolicyPrincipalAttachment.md +2 -7
- package/dist/okf/types/PortalProduct.md +24 -0
- package/dist/okf/types/PrefetchSchedule.md +25 -0
- package/dist/okf/types/PricingPlanManagerSubscription.md +31 -0
- package/dist/okf/types/PrincipalAssociation.md +27 -0
- package/dist/okf/types/PrivateDnsNamespace.md +8 -8
- package/dist/okf/types/PrivateVirtualInterface.md +1 -0
- package/dist/okf/types/ProcurementPortalPreference.md +45 -0
- package/dist/okf/types/Program.md +33 -0
- package/dist/okf/types/ProjectMembership.md +1 -1
- package/dist/okf/types/ProtocolsList.md +26 -0
- package/dist/okf/types/PublicDnsNamespace.md +7 -7
- package/dist/okf/types/PublicVirtualInterface.md +1 -0
- package/dist/okf/types/QEV2IdcApplication.md +25 -0
- package/dist/okf/types/QueryLoggingConfig.md +21 -0
- package/dist/okf/types/QuerySuggestionsBlockList.md +25 -0
- package/dist/okf/types/QuickSightAssignment.md +24 -0
- package/dist/okf/types/RAMResourceAssociation.md +27 -0
- package/dist/okf/types/RDSClusterSnapshot.md +54 -0
- package/dist/okf/types/RDSDBParameterGroup.md +5 -0
- package/dist/okf/types/RDSDeployment.md +41 -0
- package/dist/okf/types/RcsAgent.md +38 -0
- package/dist/okf/types/ReceiptRule.md +5 -5
- package/dist/okf/types/ReceiptRuleSet.md +1 -6
- package/dist/okf/types/RecommenderFilter.md +27 -0
- package/dist/okf/types/RecommenderSchema.md +25 -0
- package/dist/okf/types/RecordSet.md +16 -22
- package/dist/okf/types/RecoveryPlan.md +28 -0
- package/dist/okf/types/RedshiftIdcApplication.md +31 -0
- package/dist/okf/types/RedshiftSnapshot.md +59 -0
- package/dist/okf/types/RegistrationAttachment.md +28 -0
- package/dist/okf/types/Registry.md +41 -0
- package/dist/okf/types/RegistryRecord.md +38 -0
- package/dist/okf/types/RelatedItem.md +24 -0
- package/dist/okf/types/ReplicationConfigurationTemplate.md +35 -0
- package/dist/okf/types/ReplicationSubnetGroup.md +4 -9
- package/dist/okf/types/ReplicationTask.md +14 -14
- package/dist/okf/types/ReportGenerator.md +29 -0
- package/dist/okf/types/ReportGroup.md +1 -3
- package/dist/okf/types/ResilienceHubV2Policy.md +1 -0
- package/dist/okf/types/ResilienceHubV2Service.md +1 -0
- package/dist/okf/types/ResourceConfiguration.md +1 -1
- package/dist/okf/types/ResourceMetricsConfiguration.md +21 -0
- package/dist/okf/types/RestApi.md +1 -0
- package/dist/okf/types/RetrievalInstruction.md +32 -0
- package/dist/okf/types/RouterOutput.md +1 -0
- package/dist/okf/types/Rule.md +31 -0
- package/dist/okf/types/RunCache.md +29 -0
- package/dist/okf/types/Runtime.md +2 -1
- package/dist/okf/types/SCNInstance.md +33 -0
- package/dist/okf/types/SDBDomain.md +2 -2
- package/dist/okf/types/SMBFileShare.md +49 -0
- package/dist/okf/types/SageMakerArtifact.md +27 -0
- package/dist/okf/types/SageMakerEndpoint.md +0 -1
- package/dist/okf/types/ScalableTarget.md +1 -0
- package/dist/okf/types/ScalingPlan.md +6 -6
- package/dist/okf/types/ScheduledReport.md +31 -0
- package/dist/okf/types/SecondaryNetwork.md +26 -0
- package/dist/okf/types/SecurityAgentArtifact.md +25 -0
- package/dist/okf/types/SecurityAgentIntegration.md +31 -0
- package/dist/okf/types/Server.md +1 -0
- package/dist/okf/types/ServerlessCache.md +2 -0
- package/dist/okf/types/ServerlessCacheSnapshot.md +31 -0
- package/dist/okf/types/ServerlessRepoApplication.md +32 -0
- package/dist/okf/types/ServiceDiscoveryInstance.md +3 -7
- package/dist/okf/types/SipMediaApplication.md +27 -0
- package/dist/okf/types/SiteToSiteVpnAttachment.md +2 -0
- package/dist/okf/types/SnapshotCopyGrant.md +20 -0
- package/dist/okf/types/Solution.md +1 -0
- package/dist/okf/types/SourceAssociation.md +25 -0
- package/dist/okf/types/SourceCredential.md +6 -6
- package/dist/okf/types/SourceNetwork.md +23 -0
- package/dist/okf/types/StackFleetAssociation.md +2 -7
- package/dist/okf/types/StorageTierPolicy.md +20 -0
- package/dist/okf/types/StorageVirtualMachine.md +9 -9
- package/dist/okf/types/Stream.md +28 -0
- package/dist/okf/types/SubnetCidrReservation.md +26 -0
- package/dist/okf/types/SubscriptionProvider.md +26 -0
- package/dist/okf/types/SupportPermit.md +29 -0
- package/dist/okf/types/Table.md +2 -1
- package/dist/okf/types/TableOptimizer.md +5 -10
- package/dist/okf/types/Tape.md +31 -0
- package/dist/okf/types/Template.md +36 -0
- package/dist/okf/types/Tenant.md +2 -0
- package/dist/okf/types/Terminology.md +39 -0
- package/dist/okf/types/Thesaurus.md +25 -0
- package/dist/okf/types/ThingPrincipalAttachment.md +3 -8
- package/dist/okf/types/Topic.md +1 -0
- package/dist/okf/types/TopicRuleDestination.md +1 -0
- package/dist/okf/types/TrafficPolicy.md +26 -0
- package/dist/okf/types/TrafficPolicyInstance.md +28 -0
- package/dist/okf/types/TranscribeVocabulary.md +27 -0
- package/dist/okf/types/TransitGatewayRouteTableAttachment.md +2 -0
- package/dist/okf/types/TransitVirtualInterface.md +1 -0
- package/dist/okf/types/Tunnel.md +25 -0
- package/dist/okf/types/UsageLimit.md +26 -0
- package/dist/okf/types/UseCase.md +23 -0
- package/dist/okf/types/User.md +47 -0
- package/dist/okf/types/VPCEndpoint.md +1 -1
- package/dist/okf/types/VPCEndpointService.md +6 -0
- package/dist/okf/types/VPCPeeringConnection.md +2 -2
- package/dist/okf/types/VPNConcentrator.md +1 -1
- package/dist/okf/types/VPNConnection.md +1 -1
- package/dist/okf/types/VerifiedDestinationNumber.md +25 -0
- package/dist/okf/types/View.md +27 -0
- package/dist/okf/types/VoiceConnector.md +30 -0
- package/dist/okf/types/Volume.md +44 -0
- package/dist/okf/types/Vpc.md +1 -1
- package/dist/okf/types/VpcAttachment.md +2 -0
- package/dist/okf/types/WebFunction.md +27 -0
- package/dist/okf/types/WebFunctionEndpoint.md +44 -0
- package/dist/okf/types/WebFunctionRevision.md +32 -0
- package/dist/okf/types/WickrNetwork.md +27 -0
- package/dist/okf/types/Worker.md +29 -0
- package/dist/okf/types/Workforce.md +26 -0
- package/dist/okf/types/Workload.md +35 -0
- package/dist/okf/types/WorkloadEstimate.md +35 -0
- package/dist/okf/types/Workspace.md +28 -0
- package/dist/okf/types/Workteam.md +8 -8
- package/dist/op/activities/aws-apply.js +214 -0
- package/dist/op/activities/floci.js +97 -0
- package/dist/op/activities/index.js +32 -0
- package/dist/op/builders.js +50 -0
- package/dist/ownership.js +52 -0
- package/dist/package-cli.js +25 -0
- package/dist/parameter.js +19 -0
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +1006 -0
- package/dist/properties.js +166 -0
- package/dist/pseudo.js +25 -0
- package/dist/receipt-store.d.ts.map +1 -1
- package/dist/receipt-store.js +233 -0
- package/dist/reference-catalog.js +106 -0
- package/dist/rules/ext001.ts +3 -3
- package/dist/rules/waw016.ts +2 -2
- package/dist/serializer.js +529 -0
- package/dist/spec/fetch.js +193 -0
- package/dist/spec/parse.js +259 -0
- package/dist/spec/pin.js +185 -0
- package/dist/spec/pinned-types.json +203 -0
- package/dist/stack-errors.js +14 -0
- package/dist/taggable.d.ts.map +1 -1
- package/dist/taggable.js +33 -0
- package/dist/teardown.js +199 -0
- package/dist/template-sections.js +53 -0
- package/dist/template-transform.js +50 -0
- package/dist/types/index.d.ts +18847 -1124
- package/dist/validate-cli.js +16 -0
- package/dist/validate.js +33 -0
- package/package.json +9 -9
- package/src/agentcore/trace-fetch.ts +2 -1
- package/src/api/credential-chain.ts +119 -9
- package/src/api/credential-isolation.test.ts +72 -0
- package/src/api/read-client-chain.test.ts +159 -0
- package/src/api/read-client.ts +42 -6
- package/src/api/sigv4.ts +4 -4
- package/src/caller-identity.ts +3 -5
- package/src/codegen/any-budget.test.ts +12 -2
- package/src/codegen/generate.ts +9 -0
- package/src/codegen/package.ts +2 -2
- package/src/codegen/patches.test.ts +95 -0
- package/src/codegen/patches.ts +53 -9
- package/src/codegen/property-overlay.json +1 -16
- package/src/components/apply.ts +218 -6
- package/src/components/cfn-plan-floci.e2e.test.ts +76 -0
- package/src/components/cfn-plan.test.ts +225 -16
- package/src/components/cloud-executor.ts +73 -25
- package/src/deep-observe.ts +2 -1
- package/src/disruption.ts +2 -1
- package/src/generated/index.d.ts +18847 -1124
- package/src/generated/index.ts +1376 -161
- package/src/generated/lexicon-aws.json +17359 -784
- package/src/identity-observe.ts +2 -1
- package/src/lint/post-synth/ext001.ts +3 -3
- package/src/lint/post-synth/waw016.ts +2 -2
- package/src/lsp/completions.ts +2 -1
- package/src/lsp/hover.ts +2 -1
- package/src/plugin.ts +2 -1
- package/src/receipt-store.ts +2 -1
- package/src/spec/pin.ts +3 -3
- package/src/spec/pinned-types.json +203 -0
- package/src/taggable.ts +2 -2
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `extract-config-bom` capability (#613, epic #551 follow-up to #606).
|
|
3
|
+
*
|
|
4
|
+
* chant synthesis is deterministic, so a synthesized IaC template (the
|
|
5
|
+
* CloudFormation JSON `chant build` already produces — see ../../build.ts
|
|
6
|
+
* and lexicons/aws/src/serializer.ts's `CFTemplate`) is itself a
|
|
7
|
+
* reproducible artifact with a legitimate bill-of-materials: it declares
|
|
8
|
+
* resources, may nest child stacks, and references external artifacts
|
|
9
|
+
* (container image digests, AMI ids, other lexicons' versions) that are not
|
|
10
|
+
* declared dependencies in any lockfile. This module is the config-BOM
|
|
11
|
+
* analogue of ./sbom.ts's `generate-sbom`: same archive/manifest wiring,
|
|
12
|
+
* same SPDX/CycloneDX writer (./bom-writer.ts), different subject (a
|
|
13
|
+
* template's structure instead of a lockfile's package list).
|
|
14
|
+
*
|
|
15
|
+
* **Scope.** The extractor is a pure, hermetic AST-ish walk over the
|
|
16
|
+
* template's already-parsed JSON — no cloud calls, no `cfn describe-stacks`,
|
|
17
|
+
* no network. It only reads chant's own synthesized output, so it works
|
|
18
|
+
* identically for any lexicon whose serializer emits a JSON document shaped
|
|
19
|
+
* like CloudFormation's `{ Resources: { name: { Type, Properties } } }` (the
|
|
20
|
+
* ../../serializer.ts `SerializerResult.primary`/`files` convention every
|
|
21
|
+
* lexicon serializer already produces). Non-JSON serializer output (a raw
|
|
22
|
+
* Kubernetes YAML manifest, say) is out of scope for this first cut — see
|
|
23
|
+
* `extractConfigBom`'s doc comment.
|
|
24
|
+
*
|
|
25
|
+
* **Why config-only/infra components get a BOM.** #606 shipped
|
|
26
|
+
* `generate-sbom` keyed to *artifact* types (image/jar/zip/dir); a
|
|
27
|
+
* config-only component (no `build` phase, e.g. a DynamoDB table or an EMR
|
|
28
|
+
* cluster definition — see epic #551's "Infra" archetype) has none of those
|
|
29
|
+
* and so was previously assumed to have nothing to attach a BOM to. That
|
|
30
|
+
* assumption undercounts what's true: the synthesized template *is* that
|
|
31
|
+
* component's build output. Treating it as a first-class archive artifact
|
|
32
|
+
* (a `template`-kind entry with its own content digest, peer to `image`/
|
|
33
|
+
* `asset` — see ./build-archive.ts's `addArchiveTemplate`) means a
|
|
34
|
+
* config-BOM can attach to it exactly the way a software SBOM attaches to
|
|
35
|
+
* an image digest, closing the gap.
|
|
36
|
+
*/
|
|
37
|
+
import { addArchiveEntry, archiveRelativePath, contentDigest, createBuildArchiveManifest, } from "@intentius/chant/components/verbs/build-archive";
|
|
38
|
+
import { writeBom } from "@intentius/chant/components/verbs/bom-writer";
|
|
39
|
+
import { DEFAULT_SBOM_FORMAT } from "@intentius/chant/components/verbs/sbom-generator";
|
|
40
|
+
import { writeFileSync, mkdirSync } from "node:fs";
|
|
41
|
+
import { join } from "node:path";
|
|
42
|
+
/** CloudFormation resource type used for nested stacks (see lexicons/aws/src/nested-stack.ts). Other lexicons' nesting resource types can be added here as they gain the same concept. */
|
|
43
|
+
const NESTED_STACK_TYPES = new Set(["AWS::CloudFormation::Stack"]);
|
|
44
|
+
/** Property names known to carry a nested stack's child template location, checked in order. */
|
|
45
|
+
function extractTemplatePath(properties) {
|
|
46
|
+
const templateUrl = properties?.TemplateURL;
|
|
47
|
+
if (typeof templateUrl === "string")
|
|
48
|
+
return templateUrl;
|
|
49
|
+
if (templateUrl && typeof templateUrl === "object") {
|
|
50
|
+
// { "Fn::Sub": "${TemplateBasePath}/network.template.json" } — pull the filename back out.
|
|
51
|
+
const sub = templateUrl["Fn::Sub"];
|
|
52
|
+
if (typeof sub === "string") {
|
|
53
|
+
const match = sub.match(/([^/{}$]+\.template\.json)$/);
|
|
54
|
+
if (match)
|
|
55
|
+
return match[1];
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
60
|
+
/** AMI id pattern (`ami-` followed by 8 or 17 hex chars, matching both legacy and current EC2 id formats). */
|
|
61
|
+
const AMI_PATTERN = /^ami-[0-9a-f]{8}([0-9a-f]{9})?$/;
|
|
62
|
+
/** OCI/Docker content digest pattern (`sha256:<64 hex chars>`), the same form ./build-archive.ts's `contentDigest` produces. */
|
|
63
|
+
const DIGEST_PATTERN = /^sha256:[0-9a-f]{64}$/;
|
|
64
|
+
/** A bare `image:tag@sha256:digest` or `image@sha256:digest` reference. */
|
|
65
|
+
const IMAGE_DIGEST_REF_PATTERN = /@(sha256:[0-9a-f]{64})$/;
|
|
66
|
+
/** Property names likely to carry a lexicon version string, so a bare semver value there is attributed as `lexicon-version` rather than left unclassified. */
|
|
67
|
+
const LEXICON_VERSION_PROPERTY_NAMES = new Set(["LexiconVersion", "lexiconVersion", "ChantLexiconVersion"]);
|
|
68
|
+
/** Walk one resource's `Properties` tree (recursively, since a reference can be nested inside e.g. a container definition list) collecting external references. */
|
|
69
|
+
function scanPropertiesForReferences(resourceName, properties, propertyKeyHint, out) {
|
|
70
|
+
if (properties === null || properties === undefined)
|
|
71
|
+
return;
|
|
72
|
+
if (typeof properties === "string") {
|
|
73
|
+
if (AMI_PATTERN.test(properties)) {
|
|
74
|
+
out.push({ kind: "ami", value: properties, resourceName });
|
|
75
|
+
}
|
|
76
|
+
else if (DIGEST_PATTERN.test(properties) || IMAGE_DIGEST_REF_PATTERN.test(properties)) {
|
|
77
|
+
const digestMatch = properties.match(IMAGE_DIGEST_REF_PATTERN);
|
|
78
|
+
out.push({ kind: "image-digest", value: digestMatch ? digestMatch[1] : properties, resourceName });
|
|
79
|
+
}
|
|
80
|
+
else if (propertyKeyHint && LEXICON_VERSION_PROPERTY_NAMES.has(propertyKeyHint) && /^\d+\.\d+\.\d+/.test(properties)) {
|
|
81
|
+
out.push({ kind: "lexicon-version", value: properties, resourceName });
|
|
82
|
+
}
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
if (Array.isArray(properties)) {
|
|
86
|
+
for (const item of properties)
|
|
87
|
+
scanPropertiesForReferences(resourceName, item, propertyKeyHint, out);
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
if (typeof properties === "object") {
|
|
91
|
+
for (const [key, value] of Object.entries(properties)) {
|
|
92
|
+
scanPropertiesForReferences(resourceName, value, key, out);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Walk a synthesized template's parsed JSON, enumerating declared resources,
|
|
98
|
+
* nested stack/module references, and external artifact references (image
|
|
99
|
+
* digests, AMI ids, lexicon versions found in resource properties).
|
|
100
|
+
*
|
|
101
|
+
* Deliberately structural, not semantic: this never talks to AWS/any cloud
|
|
102
|
+
* to resolve what an AMI id or image digest actually *is* — it only records
|
|
103
|
+
* that a resource's properties reference one, the same "surface the
|
|
104
|
+
* reference, don't interpret it" stance ./sbom-generator.ts's module doc
|
|
105
|
+
* takes for SBOM content generally.
|
|
106
|
+
*/
|
|
107
|
+
export function inventoryTemplate(templateJson) {
|
|
108
|
+
const template = JSON.parse(templateJson);
|
|
109
|
+
const resources = [];
|
|
110
|
+
const nestedStacks = [];
|
|
111
|
+
const externalReferences = [];
|
|
112
|
+
for (const [name, resource] of Object.entries(template.Resources ?? {})) {
|
|
113
|
+
const type = resource.Type ?? "Unknown";
|
|
114
|
+
resources.push({ name, type });
|
|
115
|
+
if (NESTED_STACK_TYPES.has(type)) {
|
|
116
|
+
nestedStacks.push({ resourceName: name, templatePath: extractTemplatePath(resource.Properties) });
|
|
117
|
+
}
|
|
118
|
+
scanPropertiesForReferences(name, resource.Properties, undefined, externalReferences);
|
|
119
|
+
}
|
|
120
|
+
return { resources, nestedStacks, externalReferences };
|
|
121
|
+
}
|
|
122
|
+
/** Project a `ConfigBomInventory` into the standard-agnostic `BomPackage[]` shape ./bom-writer.ts's writers consume. Every declared resource becomes a `type: "config"` component; every external reference becomes a `type: "external-reference"` component, so a config-BOM reader sees "what chant declared" and "what chant points at but doesn't own" as distinguishable entries rather than a flat, ambiguous list. */
|
|
123
|
+
export function inventoryToBomPackages(inventory) {
|
|
124
|
+
const resourcePackages = inventory.resources.map((r) => ({
|
|
125
|
+
name: r.name,
|
|
126
|
+
version: r.type,
|
|
127
|
+
type: "config",
|
|
128
|
+
}));
|
|
129
|
+
const nestedStackNames = new Set(inventory.nestedStacks.map((n) => n.resourceName));
|
|
130
|
+
for (const pkg of resourcePackages) {
|
|
131
|
+
if (nestedStackNames.has(pkg.name)) {
|
|
132
|
+
const nested = inventory.nestedStacks.find((n) => n.resourceName === pkg.name);
|
|
133
|
+
if (nested?.templatePath)
|
|
134
|
+
pkg.purl = `chant:nested-stack/${nested.templatePath}`;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
const referencePackages = inventory.externalReferences.map((ref, i) => ({
|
|
138
|
+
name: `${ref.kind}:${ref.resourceName ?? "unknown"}:${i}`,
|
|
139
|
+
version: ref.value,
|
|
140
|
+
type: "external-reference",
|
|
141
|
+
}));
|
|
142
|
+
return [...resourcePackages, ...referencePackages];
|
|
143
|
+
}
|
|
144
|
+
/** Default archive path for a generated config-BOM when `into` is omitted: `<template path>.config-bom.json`. */
|
|
145
|
+
function defaultConfigBomPath(templatePath) {
|
|
146
|
+
return `${archiveRelativePath(templatePath)}.config-bom.json`;
|
|
147
|
+
}
|
|
148
|
+
/** Tool name recorded on the archive entry / BOM document — surfaced the same way `generate-sbom` records `sbom.generator` (e.g. "syft-1.2.3"). */
|
|
149
|
+
const CONFIG_BOM_GENERATOR = "chant-config-bom-extractor";
|
|
150
|
+
/**
|
|
151
|
+
* Extract a config-BOM from a synthesized IaC template's declared resources,
|
|
152
|
+
* nested stacks, and external references, and fold the result into the
|
|
153
|
+
* build-archive manifest as an `sbom`-kind entry (`bomKind: "config"`) linked
|
|
154
|
+
* to the template artifact's digest — the config-BOM peer of `generate-sbom`
|
|
155
|
+
* (./sbom.ts). No rollback, for the same reason `generate-sbom` declares
|
|
156
|
+
* none: an already-generated, content-addressed BOM is evidence, not mutable
|
|
157
|
+
* state to compensate.
|
|
158
|
+
*/
|
|
159
|
+
export function createExtractConfigBomCapability() {
|
|
160
|
+
return {
|
|
161
|
+
kind: "extract-config-bom",
|
|
162
|
+
async run(ctx, input) {
|
|
163
|
+
const templatePath = archiveRelativePath(input.path);
|
|
164
|
+
const format = input.format ?? DEFAULT_SBOM_FORMAT;
|
|
165
|
+
const inventory = inventoryTemplate(input.content);
|
|
166
|
+
const packages = inventoryToBomPackages(inventory);
|
|
167
|
+
const doc = writeBom(format, {
|
|
168
|
+
subjectName: templatePath,
|
|
169
|
+
subjectId: input.digest ?? contentDigest(input.content),
|
|
170
|
+
packages,
|
|
171
|
+
generator: CONFIG_BOM_GENERATOR,
|
|
172
|
+
}, input.now);
|
|
173
|
+
const bom = { ...doc, packageCount: packages.length, generator: CONFIG_BOM_GENERATOR };
|
|
174
|
+
if (input.outDir) {
|
|
175
|
+
mkdirSync(input.outDir, { recursive: true });
|
|
176
|
+
writeFileSync(join(input.outDir, `config-bom.${format}.json`), bom.bytes);
|
|
177
|
+
}
|
|
178
|
+
const into = input.into ?? defaultConfigBomPath(input.path);
|
|
179
|
+
const digest = contentDigest(bom.bytes);
|
|
180
|
+
const base = input.manifest ?? createBuildArchiveManifest(ctx.component);
|
|
181
|
+
const manifest = addArchiveEntry(base, {
|
|
182
|
+
kind: "sbom",
|
|
183
|
+
bomKind: "config",
|
|
184
|
+
path: into,
|
|
185
|
+
digest,
|
|
186
|
+
mediaType: bom.mediaType,
|
|
187
|
+
subjectDigest: input.digest,
|
|
188
|
+
packageCount: bom.packageCount,
|
|
189
|
+
generator: bom.generator,
|
|
190
|
+
});
|
|
191
|
+
return { bom, inventory, archivePath: into, digest, manifest };
|
|
192
|
+
},
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Default `extract-config-bom` capability. Pure/hermetic — no injectable
|
|
197
|
+
* backend needed since template inventory is a structural walk, not a scan
|
|
198
|
+
* requiring an external tool.
|
|
199
|
+
*
|
|
200
|
+
* Typically composed immediately after `addArchiveTemplate` (./build.ts) in
|
|
201
|
+
* a config-only/infra component's build phase — `addArchiveTemplate` folds
|
|
202
|
+
* the synthesized template into the archive as a first-class `template`-kind
|
|
203
|
+
* entry with its own content digest (#613 — IaC as a first-class build
|
|
204
|
+
* artifact, peer to `image`/`jar`), and this capability attaches the
|
|
205
|
+
* resulting config-BOM to that same digest.
|
|
206
|
+
*/
|
|
207
|
+
export const extractConfigBomCapability = createExtractConfigBomCapability();
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* host / code delivery family — run against a mutable host.
|
|
3
|
+
*
|
|
4
|
+
* `code-deploy` (AWS CodeDeploy) is the managed, nearly AWS-only leaf: create
|
|
5
|
+
* a deployment of a revision (S3/GitHub) to a deployment group, appspec-driven
|
|
6
|
+
* lifecycle hooks (BeforeInstall/AfterInstall/ApplicationStart/ValidateService),
|
|
7
|
+
* in-place or blue/green, native automatic rollback, wait for terminal status.
|
|
8
|
+
* Pairs with `publish-artifact` — the revision is the published S3 bundle
|
|
9
|
+
* (`@publish.uri`).
|
|
10
|
+
*
|
|
11
|
+
* `copy-to-host` / `remote-exec` (SSM Run Command or SSH) are the portable,
|
|
12
|
+
* lower-level generic verbs for host bootstrap, on-host migrations, and
|
|
13
|
+
* single-host compose where CodeDeploy is not used or not available
|
|
14
|
+
* (no clean Azure/GCP peer — see docs/components/cloud-boundary).
|
|
15
|
+
*
|
|
16
|
+
* `code-deploy` is a real implementation (#557, epic #551) over the
|
|
17
|
+
* injectable `CloudExecutor` (./cloud-executor.ts) — the capability the
|
|
18
|
+
* Neo4j fan-out pilot uses once per instance. `copy-to-host` and `remote-exec`
|
|
19
|
+
* are also real, over the executor's `host.exec` (SSM Run Command, waited to
|
|
20
|
+
* completion); the SSH transport is not yet implemented.
|
|
21
|
+
*/
|
|
22
|
+
import { defaultCloudExecutor } from "./cloud-executor.js";
|
|
23
|
+
import { releaseEnvironment } from "@intentius/chant/telemetry-attribution";
|
|
24
|
+
/** Normalize `CodeDeployInput.revision` to the strict `{type, uri|repository+commitId}` shape the executor takes. */
|
|
25
|
+
function normalizeRevision(revision) {
|
|
26
|
+
return typeof revision === "string" ? { type: "s3", uri: revision } : revision;
|
|
27
|
+
}
|
|
28
|
+
/** Resolve the application/deployment-group names, defaulting from `ctx.component`/`instance` when the input omits them (matches the Neo4j pilot's per-instance shorthand). */
|
|
29
|
+
function resolveTargets(ctx, input) {
|
|
30
|
+
const application = input.application ?? ctx.component;
|
|
31
|
+
const deploymentGroup = input.deploymentGroup ?? (input.instance !== undefined ? `${application}-${input.instance}` : application);
|
|
32
|
+
return { application, deploymentGroup };
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Deploy a revision to a host (fleet) via AWS CodeDeploy: create the
|
|
36
|
+
* deployment, then wait for a terminal status. Rollback re-invokes
|
|
37
|
+
* `stopAndRollback` against the deployment id this step created (captured in
|
|
38
|
+
* a closure-scoped map keyed by application/deploymentGroup; the driver now
|
|
39
|
+
* also passes `run`'s output as `rollback`'s optional third arg (#1944), but
|
|
40
|
+
* this capability's input-derived key needs neither channel to resolve
|
|
41
|
+
* identity) — riding CodeDeploy's own native automatic rollback to the
|
|
42
|
+
* last known-good revision rather than a chant-scripted compensation, the
|
|
43
|
+
* "auto" rollback style the Neo4j pilot's docs comment contrasts with the
|
|
44
|
+
* ALB/ECS pilot's component-declared one.
|
|
45
|
+
*/
|
|
46
|
+
export function createCodeDeployCapability(executor = defaultCloudExecutor()) {
|
|
47
|
+
const lastDeploymentByTarget = new Map();
|
|
48
|
+
return {
|
|
49
|
+
kind: "code-deploy",
|
|
50
|
+
async run(ctx, input) {
|
|
51
|
+
const { application, deploymentGroup } = resolveTargets(ctx, input);
|
|
52
|
+
const { deploymentId } = await executor.codeDeploy.createDeployment({
|
|
53
|
+
application,
|
|
54
|
+
deploymentGroup,
|
|
55
|
+
revision: normalizeRevision(input.revision),
|
|
56
|
+
strategy: input.strategy,
|
|
57
|
+
});
|
|
58
|
+
lastDeploymentByTarget.set(`${application}/${deploymentGroup}`, deploymentId);
|
|
59
|
+
const { status } = await executor.codeDeploy.waitForDeployment(deploymentId);
|
|
60
|
+
if (status !== "Succeeded") {
|
|
61
|
+
throw new Error(`code-deploy "${application}/${deploymentGroup}": deployment ${deploymentId} ended ${status}`);
|
|
62
|
+
}
|
|
63
|
+
return { deploymentId, status };
|
|
64
|
+
},
|
|
65
|
+
async rollback(ctx, input) {
|
|
66
|
+
const { application, deploymentGroup } = resolveTargets(ctx, input);
|
|
67
|
+
const deploymentId = lastDeploymentByTarget.get(`${application}/${deploymentGroup}`);
|
|
68
|
+
if (!deploymentId)
|
|
69
|
+
return; // nothing this capability instance deployed for this target — nothing to unwind.
|
|
70
|
+
await executor.codeDeploy.stopAndRollback(deploymentId);
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
/** Default `code-deploy` capability, backed by the real `CloudExecutor`. */
|
|
75
|
+
export const codeDeployCapability = createCodeDeployCapability();
|
|
76
|
+
/**
|
|
77
|
+
* Copy a file to a host via SSM Run Command: the host pulls `from` (an S3 URI)
|
|
78
|
+
* to `to` with `aws s3 cp`, then `stat`s the result for the byte count. `from`
|
|
79
|
+
* must be reachable from the host (typically a prior `publish-artifact`'s URI).
|
|
80
|
+
*/
|
|
81
|
+
export function createCopyToHostCapability(executor = defaultCloudExecutor()) {
|
|
82
|
+
return {
|
|
83
|
+
kind: "copy-to-host",
|
|
84
|
+
rollbackPolicy: "needs-opt-out",
|
|
85
|
+
async run(_ctx, input) {
|
|
86
|
+
const { stdout } = await executor.host.exec({
|
|
87
|
+
host: input.host,
|
|
88
|
+
command: `aws s3 cp ${input.from} ${input.to} >/dev/null 2>&1 && stat -c %s ${input.to}`,
|
|
89
|
+
});
|
|
90
|
+
return { bytesCopied: Number.parseInt(stdout.trim(), 10) || 0 };
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
/** Default `copy-to-host` capability, backed by the real `CloudExecutor`. */
|
|
95
|
+
export const copyToHostCapability = createCopyToHostCapability();
|
|
96
|
+
/**
|
|
97
|
+
* Run a command on a remote host via SSM Run Command, waiting for it to finish
|
|
98
|
+
* and returning its stdout + exit code. SSH transport is not yet supported.
|
|
99
|
+
*/
|
|
100
|
+
export function createRemoteExecCapability(executor = defaultCloudExecutor()) {
|
|
101
|
+
return {
|
|
102
|
+
kind: "remote-exec",
|
|
103
|
+
rollbackPolicy: "needs-opt-out",
|
|
104
|
+
async run(ctx, input) {
|
|
105
|
+
if (input.via === "ssh") {
|
|
106
|
+
throw new Error(`remote-exec: ssh transport not yet supported for host "${input.host}" — use the default ssm transport`);
|
|
107
|
+
}
|
|
108
|
+
// A release run exports its attributes on the host (#3061, ws-081), so a `docker compose up`
|
|
109
|
+
// fills the Compose file's `${CHANT_RELEASE_ATTRIBUTES:-}`. The value is percent-encoded, so
|
|
110
|
+
// single quotes hold it.
|
|
111
|
+
const exports = Object.entries(releaseEnvironment(ctx.release)).map(([k, v]) => `export ${k}='${v}'; `).join("");
|
|
112
|
+
return executor.host.exec({ host: input.host, command: `${exports}${input.command}`, cwd: input.cwd });
|
|
113
|
+
},
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
/** Default `remote-exec` capability, backed by the real `CloudExecutor`. */
|
|
117
|
+
export const remoteExecCapability = createRemoteExecCapability();
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The aws lexicon's component/release surface: the AWS-leaf capabilities, their
|
|
3
|
+
* typed step-builders, the injectable aws `CloudExecutor`, and the
|
|
4
|
+
* `awsCapabilityPlugin` core loads when a project declares `lexicons: ["aws"]`.
|
|
5
|
+
* Component authors import the AWS verbs' builders from here
|
|
6
|
+
* (`@intentius/chant-lexicon-aws/components`), the way agnostic verbs come from
|
|
7
|
+
* `@intentius/chant/components`.
|
|
8
|
+
*/
|
|
9
|
+
export { awsCapabilityPlugin, AWS_VERB_FAMILIES } from "./capability-plugin.js";
|
|
10
|
+
export * from "./builders.js";
|
|
11
|
+
export * from "./config-bom.js";
|
|
12
|
+
export * from "./apply.js";
|
|
13
|
+
export * from "./job-submission.js";
|
|
14
|
+
export * from "./host-delivery.js";
|
|
15
|
+
export * from "./safety.js";
|
|
16
|
+
export * from "./wait-aws.js";
|
|
17
|
+
export * from "./publish.js";
|
|
18
|
+
export * from "./cloud-executor.js";
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* job submission family — point a running compute service at an artifact.
|
|
3
|
+
* Cloud-shaped (EMR here; the same shape reuses for Glue / Batch / Step
|
|
4
|
+
* Functions / SageMaker per docs/components/cloud-boundary). Typically
|
|
5
|
+
* consumes a producer component's published artifact, e.g.
|
|
6
|
+
* `jar: "@jar-lib.publish.uri"`.
|
|
7
|
+
*
|
|
8
|
+
* `emr-start-job-run` is a real implementation (#561, epic #551) — just
|
|
9
|
+
* enough against the injectable `CloudExecutor` (./cloud-executor.ts) to run
|
|
10
|
+
* the JAR-producer -> EMR-consumer cross-component example end to end (a
|
|
11
|
+
* mocked cloud is acceptable per #561's acceptance criteria; the full EMR
|
|
12
|
+
* surface — retries, Serverless vs EMR-on-EC2 branching, Glue/Batch peers —
|
|
13
|
+
* stays out of scope, per #561 explicitly deferring "the emr-start-job-run
|
|
14
|
+
* cloud impl beyond what the example needs"). `emr-submit-step` is a
|
|
15
|
+
* different verb (submit a step to an already-running EMR-on-EC2 cluster
|
|
16
|
+
* rather than starting an ephemeral job run), also real over the executor
|
|
17
|
+
* (`aws emr add-steps`) and unit-tested against the mock — the same
|
|
18
|
+
* "mocked cloud is acceptable" basis #561 set for its sibling, since a live
|
|
19
|
+
* long-running EMR cluster is not part of gating CI.
|
|
20
|
+
*/
|
|
21
|
+
import { defaultCloudExecutor } from "./cloud-executor.js";
|
|
22
|
+
/**
|
|
23
|
+
* Start an EMR job run (Serverless application or EMR-on-EC2 cluster)
|
|
24
|
+
* against a published artifact. `input.jar` arrives already resolved by the
|
|
25
|
+
* driver's graph-driven wiring (`@<component>.publish.uri`) — this capability
|
|
26
|
+
* never resolves the reference itself, keeping cross-component wiring
|
|
27
|
+
* entirely the graph's job (../driver.ts's `resolveWiring`), never a
|
|
28
|
+
* capability- or orchestrator-level special case. No rollback: starting a
|
|
29
|
+
* job run has no "undo" that restores prior state — a failed/cancelled run
|
|
30
|
+
* simply produced no usable output, matching `wait-for-stack`/`wait-job`'s
|
|
31
|
+
* read-only-observation story (there is nothing to compensate for having
|
|
32
|
+
* asked the cluster to run something).
|
|
33
|
+
*/
|
|
34
|
+
export function createEmrStartJobRunCapability(executor = defaultCloudExecutor()) {
|
|
35
|
+
return {
|
|
36
|
+
kind: "emr-start-job-run",
|
|
37
|
+
rollbackPolicy: "needs-opt-out",
|
|
38
|
+
async run(ctx, input) {
|
|
39
|
+
const clusterOrApplicationId = input.clusterOrApplicationId ?? ctx.vars?.emrApplicationId ?? ctx.component;
|
|
40
|
+
const { runId } = await executor.emr.startJobRun({
|
|
41
|
+
clusterOrApplicationId,
|
|
42
|
+
jar: input.jar,
|
|
43
|
+
args: input.args,
|
|
44
|
+
executionRoleArn: input.executionRoleArn,
|
|
45
|
+
});
|
|
46
|
+
return { runId };
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
/** Default `emr-start-job-run` capability, backed by the real `CloudExecutor`. */
|
|
51
|
+
export const emrStartJobRunCapability = createEmrStartJobRunCapability();
|
|
52
|
+
/**
|
|
53
|
+
* Submit a step to a long-running EMR-on-EC2 cluster (as opposed to
|
|
54
|
+
* `emr-start-job-run`, which starts an ephemeral Serverless/EC2 job run) via
|
|
55
|
+
* `aws emr add-steps` through the injectable `CloudExecutor`. Returns the step
|
|
56
|
+
* id for polling via `wait-job`. Like its sibling, `input.jar` arrives
|
|
57
|
+
* already resolved by the driver's graph-driven wiring, and there is no
|
|
58
|
+
* rollback — a submitted step has no "undo" that restores prior state.
|
|
59
|
+
*/
|
|
60
|
+
export function createEmrSubmitStepCapability(executor = defaultCloudExecutor()) {
|
|
61
|
+
return {
|
|
62
|
+
kind: "emr-submit-step",
|
|
63
|
+
rollbackPolicy: "needs-opt-out",
|
|
64
|
+
async run(_ctx, input) {
|
|
65
|
+
const { stepId } = await executor.emr.addStep({
|
|
66
|
+
clusterId: input.clusterId,
|
|
67
|
+
name: input.name,
|
|
68
|
+
jar: input.jar,
|
|
69
|
+
args: input.args,
|
|
70
|
+
actionOnFailure: input.actionOnFailure,
|
|
71
|
+
});
|
|
72
|
+
return { stepId };
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
/** Default `emr-submit-step` capability, backed by the real `CloudExecutor`. */
|
|
77
|
+
export const emrSubmitStepCapability = createEmrSubmitStepCapability();
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* publish family — deploy-time promotion by identity to the env location.
|
|
3
|
+
*
|
|
4
|
+
* "Make the image available at the deploy target" has more than one backend:
|
|
5
|
+
* `publish-image` promotes into a registry (ECR/ACR/Artifact Registry, pulled
|
|
6
|
+
* by the target); `load-image-on-host` copies the tarball straight onto a host
|
|
7
|
+
* and `docker load`s it (registry-less). Both satisfy the same
|
|
8
|
+
* `PublishImageBackend` interface — the backend is env config, not a pipeline
|
|
9
|
+
* fork. `publish-asset`/`publish-artifact` is the non-image sibling (S3 /
|
|
10
|
+
* CodeArtifact) used by producer/library components (e.g. a jar for EMR).
|
|
11
|
+
* See docs/components/build-archive.mdx.
|
|
12
|
+
*
|
|
13
|
+
* `publish-image` is a real implementation (#557, epic #551): it loads the
|
|
14
|
+
* archived image tarball, tags it for the destination registry, logs in via
|
|
15
|
+
* ECR, and pushes — promoting by digest, per the epic's build-once invariant.
|
|
16
|
+
*
|
|
17
|
+
* `load-image-on-host` is a real implementation (#564, epic #551 "4. Build
|
|
18
|
+
* archive + deferred publish"): it copies the archived tarball onto a host
|
|
19
|
+
* and runs `docker load` there via the injected `CloudExecutor.host` — no
|
|
20
|
+
* registry in the path at all. Both backends promote **by digest**, never
|
|
21
|
+
* rebuilding: the bytes they move are exactly what `docker-build` produced
|
|
22
|
+
* into the archive (see ./build-archive.ts). `selectPublishBackend` below is
|
|
23
|
+
* the per-environment choice between them — env config, not a pipeline fork,
|
|
24
|
+
* per docs/components/build-archive.mdx#backend-selection-is-per-environment.
|
|
25
|
+
*
|
|
26
|
+
* `publish-artifact` (aliased `publish-asset`) uploads a single archive
|
|
27
|
+
* artifact (jar/zip/asset) to S3 via `aws s3 cp` through the same
|
|
28
|
+
* endpoint-aware `CloudExecutor`, returning the object URI and a content digest
|
|
29
|
+
* of the uploaded bytes — the non-image sibling of `publish-image`.
|
|
30
|
+
*
|
|
31
|
+
* **#610 addition: publish-time SBOM/BOM referrer attach.** `publish-image`
|
|
32
|
+
* optionally registers the archive's SBOM (and, when given, the
|
|
33
|
+
* component-level aggregate BOM) as an OCI referrer on the just-pushed image
|
|
34
|
+
* digest via `oras attach` — a registry-side convenience for `oras
|
|
35
|
+
* discover`/`cosign tree` layered on top of the archive-carried copy, never a
|
|
36
|
+
* replacement for it (see ../../lifecycle/build-ledger.ts's module doc: the
|
|
37
|
+
* archive remains the universal home, working for every artifact type and
|
|
38
|
+
* the registry-less `load-image-on-host` path, which this attach step
|
|
39
|
+
* deliberately does not touch — non-image/registry-less publishes stay
|
|
40
|
+
* archive-carried only). Attach is opt-in per call (`input.sbom` supplied),
|
|
41
|
+
* guarded on `oras` availability, and never fails the publish itself: a
|
|
42
|
+
* missing `oras` binary or a failed attach is reported back on the output
|
|
43
|
+
* (`referrerAttach.attached: false` + a reason) rather than thrown, since the
|
|
44
|
+
* image is already successfully promoted by the time this step runs — the
|
|
45
|
+
* one part of this capability that is genuinely best-effort.
|
|
46
|
+
*/
|
|
47
|
+
import { readFileSync } from "node:fs";
|
|
48
|
+
import { createHash } from "node:crypto";
|
|
49
|
+
import { defaultCloudExecutor } from "./cloud-executor.js";
|
|
50
|
+
import { archiveRelativePath } from "@intentius/chant/components/verbs/build-archive";
|
|
51
|
+
import { defaultProcessRunner, q } from "@intentius/chant/components/verbs/process-runner";
|
|
52
|
+
// ── publish-image (registry backend) ────────────────────────────────────────
|
|
53
|
+
/**
|
|
54
|
+
* Attempt to `oras attach` one referrer document (SBOM or component BOM) to
|
|
55
|
+
* `imageRef`'s digest. Writes the document's bytes to a scratch file (`oras
|
|
56
|
+
* attach` reads from a file path, not stdin) and shells out through
|
|
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).
|
|
60
|
+
*/
|
|
61
|
+
async function attachOneReferrer(runner, imageRef, doc, label) {
|
|
62
|
+
try {
|
|
63
|
+
const scratchFile = `/tmp/chant-referrer-attach/${label}-${Date.now()}.json`;
|
|
64
|
+
await runner.run(`mkdir -p ${q("/tmp/chant-referrer-attach")}`);
|
|
65
|
+
await runner.run(`printf '%s' ${q(doc.bytes)} > ${q(scratchFile)}`);
|
|
66
|
+
await runner.run(`oras attach --artifact-type ${q(doc.mediaType)} ${q(imageRef)} ${q(scratchFile)}:${q(doc.mediaType)}`);
|
|
67
|
+
return { ok: true };
|
|
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 };
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Promote a built image from the archive into the environment's container
|
|
101
|
+
* registry: `docker load` the archived tarball, tag it for `to` (the env
|
|
102
|
+
* registry), `aws ecr get-login-password | docker login`, then `docker push`.
|
|
103
|
+
* Returns the pushed image's registry digest — what `cfn-deploy`/
|
|
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.
|
|
113
|
+
*/
|
|
114
|
+
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
|
+
};
|
|
146
|
+
}
|
|
147
|
+
/** Default `publish-image` capability, backed by the real `CloudExecutor`. */
|
|
148
|
+
export const publishImageCapability = createPublishImageCapability();
|
|
149
|
+
// ── load-image-on-host (host backend) ───────────────────────────────────────
|
|
150
|
+
/** Default on-host tarball destination when `hostPath` is omitted, derived from the archive path's basename. */
|
|
151
|
+
function defaultHostPath(from) {
|
|
152
|
+
const base = archiveRelativePath(from).split("/").pop() ?? "image.tar";
|
|
153
|
+
return `/tmp/chant-archive/${base}`;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Copy the image tarball straight onto a host and `docker load` it there —
|
|
157
|
+
* genuinely registry-free promotion (#564): no `docker.push`, no ECR login,
|
|
158
|
+
* no registry ever in the path. Still promotes **by digest**: the tarball
|
|
159
|
+
* copied is the exact archive artifact `docker-build` produced, so the image
|
|
160
|
+
* loaded on the host is byte-identical to the one tested in any other
|
|
161
|
+
* environment, satisfying the same build-once invariant `publish-image`
|
|
162
|
+
* does. No rollback, for the same reason `publish-image` declares none: an
|
|
163
|
+
* already-loaded, content-addressed image sitting in a host's local Docker
|
|
164
|
+
* store is not itself a problem to compensate.
|
|
165
|
+
*
|
|
166
|
+
* See docs/components/build-archive.mdx#registry-less-caveat: this makes
|
|
167
|
+
* *your built* image registry-free. Third-party images a compose file
|
|
168
|
+
* references (`postgres:16`, `redis`) still pull from their upstream
|
|
169
|
+
* registry at `compose up` unless they are archived and loaded the same way.
|
|
170
|
+
*/
|
|
171
|
+
export function createLoadImageOnHostCapability(executor = defaultCloudExecutor()) {
|
|
172
|
+
return {
|
|
173
|
+
kind: "load-image-on-host",
|
|
174
|
+
async run(_ctx, input) {
|
|
175
|
+
if (!input.host)
|
|
176
|
+
throw new Error(`load-image-on-host "${input.from}": "host" is required`);
|
|
177
|
+
const from = archiveRelativePath(input.from);
|
|
178
|
+
const to = input.hostPath ?? defaultHostPath(input.from);
|
|
179
|
+
await executor.host.copyFile({ host: input.host, from, to });
|
|
180
|
+
const { digest } = await executor.host.dockerLoad({ host: input.host, path: to });
|
|
181
|
+
return { digest, uri: `host:${input.host}#${digest}` };
|
|
182
|
+
},
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
/** Default `load-image-on-host` capability, backed by the real `CloudExecutor`. */
|
|
186
|
+
export const loadImageOnHostCapability = createLoadImageOnHostCapability();
|
|
187
|
+
/**
|
|
188
|
+
* Resolve which publish backend an environment uses, given its declared
|
|
189
|
+
* `kind` (`$env.publish.kind` in the component's env config — see
|
|
190
|
+
* docs/components/build-archive.mdx#backend-selection-is-per-environment).
|
|
191
|
+
* The decision is per environment, not per component: the same component's
|
|
192
|
+
* `Publish` phase runs `publish-image` against dev's ECR and
|
|
193
|
+
* `load-image-on-host` against a locked-down prod host, with no change to
|
|
194
|
+
* the component's own composition — only the env config `kind` differs.
|
|
195
|
+
*
|
|
196
|
+
* Accepts an optional registry of backends so a caller can extend the set
|
|
197
|
+
* (e.g. a third-party plugin registering another `PublishImageBackend`)
|
|
198
|
+
* without this function needing to change; defaults to the two starter-set
|
|
199
|
+
* backends built above.
|
|
200
|
+
*/
|
|
201
|
+
export function selectPublishBackend(kind, backends = {
|
|
202
|
+
"publish-image": publishImageCapability,
|
|
203
|
+
"load-image-on-host": loadImageOnHostCapability,
|
|
204
|
+
}) {
|
|
205
|
+
const backend = backends[kind];
|
|
206
|
+
if (!backend) {
|
|
207
|
+
throw new Error(`no publish backend registered for kind "${kind}" (known: ${Object.keys(backends).sort().join(", ")})`);
|
|
208
|
+
}
|
|
209
|
+
return backend;
|
|
210
|
+
}
|
|
211
|
+
/** Promote a non-image artifact (jar, zip, arbitrary asset) from the archive to S3/CodeArtifact. */
|
|
212
|
+
/**
|
|
213
|
+
* Publish a single archive artifact (a jar, zip, or asset) to S3 via `aws s3 cp`
|
|
214
|
+
* (endpoint-aware through the `CloudExecutor`). Returns the object's URI —
|
|
215
|
+
* referenced downstream as `@<component>.publish.uri` — and a content digest of
|
|
216
|
+
* the exact bytes uploaded.
|
|
217
|
+
*/
|
|
218
|
+
export function createPublishArtifactCapability(executor = defaultCloudExecutor()) {
|
|
219
|
+
return {
|
|
220
|
+
kind: "publish-artifact",
|
|
221
|
+
async run(_ctx, input) {
|
|
222
|
+
const localPath = archiveRelativePath(input.from);
|
|
223
|
+
const digest = `sha256:${createHash("sha256").update(readFileSync(localPath)).digest("hex")}`;
|
|
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
|
+
},
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
/** Default `publish-artifact` capability, backed by the real `CloudExecutor`. */
|
|
232
|
+
export const publishArtifactCapability = createPublishArtifactCapability();
|
|
233
|
+
/** Alias for `publish-artifact` — same capability, the docs/epic use both names for the same verb. */
|
|
234
|
+
export const publishAssetCapability = publishArtifactCapability;
|