@aws/ml-container-creator 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +202 -0
- package/LICENSE-THIRD-PARTY +68620 -0
- package/NOTICE +2 -0
- package/README.md +106 -0
- package/bin/cli.js +365 -0
- package/config/defaults.json +32 -0
- package/config/presets/transformers-djl.json +26 -0
- package/config/presets/transformers-gpu.json +24 -0
- package/config/presets/transformers-lmi.json +27 -0
- package/package.json +129 -0
- package/servers/README.md +419 -0
- package/servers/base-image-picker/catalogs/model-servers.json +1191 -0
- package/servers/base-image-picker/catalogs/python-slim.json +38 -0
- package/servers/base-image-picker/catalogs/triton-backends.json +51 -0
- package/servers/base-image-picker/catalogs/triton.json +38 -0
- package/servers/base-image-picker/index.js +495 -0
- package/servers/base-image-picker/manifest.json +17 -0
- package/servers/base-image-picker/package.json +15 -0
- package/servers/hyperpod-cluster-picker/LICENSE +202 -0
- package/servers/hyperpod-cluster-picker/index.js +424 -0
- package/servers/hyperpod-cluster-picker/manifest.json +14 -0
- package/servers/hyperpod-cluster-picker/package.json +17 -0
- package/servers/instance-recommender/LICENSE +202 -0
- package/servers/instance-recommender/catalogs/instances.json +852 -0
- package/servers/instance-recommender/index.js +284 -0
- package/servers/instance-recommender/manifest.json +16 -0
- package/servers/instance-recommender/package.json +15 -0
- package/servers/lib/LICENSE +202 -0
- package/servers/lib/bedrock-client.js +160 -0
- package/servers/lib/custom-validators.js +46 -0
- package/servers/lib/dynamic-resolver.js +36 -0
- package/servers/lib/package.json +11 -0
- package/servers/lib/schemas/image-catalog.schema.json +185 -0
- package/servers/lib/schemas/instances.schema.json +124 -0
- package/servers/lib/schemas/manifest.schema.json +64 -0
- package/servers/lib/schemas/model-catalog.schema.json +91 -0
- package/servers/lib/schemas/regions.schema.json +26 -0
- package/servers/lib/schemas/triton-backends.schema.json +51 -0
- package/servers/model-picker/catalogs/jumpstart-public.json +66 -0
- package/servers/model-picker/catalogs/popular-diffusors.json +88 -0
- package/servers/model-picker/catalogs/popular-transformers.json +226 -0
- package/servers/model-picker/index.js +1693 -0
- package/servers/model-picker/manifest.json +18 -0
- package/servers/model-picker/package.json +20 -0
- package/servers/region-picker/LICENSE +202 -0
- package/servers/region-picker/catalogs/regions.json +263 -0
- package/servers/region-picker/index.js +230 -0
- package/servers/region-picker/manifest.json +16 -0
- package/servers/region-picker/package.json +15 -0
- package/src/app.js +1007 -0
- package/src/copy-tpl.js +77 -0
- package/src/lib/accelerator-validator.js +39 -0
- package/src/lib/asset-manager.js +385 -0
- package/src/lib/aws-profile-parser.js +181 -0
- package/src/lib/bootstrap-command-handler.js +1647 -0
- package/src/lib/bootstrap-config.js +238 -0
- package/src/lib/ci-register-helpers.js +124 -0
- package/src/lib/ci-report-helpers.js +158 -0
- package/src/lib/ci-stage-helpers.js +268 -0
- package/src/lib/cli-handler.js +529 -0
- package/src/lib/comment-generator.js +544 -0
- package/src/lib/community-reports-validator.js +91 -0
- package/src/lib/config-manager.js +2106 -0
- package/src/lib/configuration-exporter.js +204 -0
- package/src/lib/configuration-manager.js +695 -0
- package/src/lib/configuration-matcher.js +221 -0
- package/src/lib/cpu-validator.js +36 -0
- package/src/lib/cuda-validator.js +57 -0
- package/src/lib/deployment-config-resolver.js +103 -0
- package/src/lib/deployment-entry-schema.js +125 -0
- package/src/lib/deployment-registry.js +598 -0
- package/src/lib/docker-introspection-validator.js +51 -0
- package/src/lib/engine-prefix-resolver.js +60 -0
- package/src/lib/huggingface-client.js +172 -0
- package/src/lib/key-value-parser.js +37 -0
- package/src/lib/known-flags-validator.js +200 -0
- package/src/lib/manifest-cli.js +280 -0
- package/src/lib/mcp-client.js +303 -0
- package/src/lib/mcp-command-handler.js +532 -0
- package/src/lib/neuron-validator.js +80 -0
- package/src/lib/parameter-schema-validator.js +284 -0
- package/src/lib/prompt-runner.js +1349 -0
- package/src/lib/prompts.js +1138 -0
- package/src/lib/registry-command-handler.js +519 -0
- package/src/lib/registry-loader.js +198 -0
- package/src/lib/rocm-validator.js +80 -0
- package/src/lib/schema-validator.js +157 -0
- package/src/lib/sensitive-redactor.js +59 -0
- package/src/lib/template-engine.js +156 -0
- package/src/lib/template-manager.js +341 -0
- package/src/lib/validation-engine.js +314 -0
- package/src/prompt-adapter.js +63 -0
- package/templates/Dockerfile +300 -0
- package/templates/IAM_PERMISSIONS.md +84 -0
- package/templates/MIGRATION.md +488 -0
- package/templates/PROJECT_README.md +439 -0
- package/templates/TEMPLATE_SYSTEM.md +243 -0
- package/templates/buildspec.yml +64 -0
- package/templates/code/chat_template.jinja +1 -0
- package/templates/code/flask/gunicorn_config.py +35 -0
- package/templates/code/flask/wsgi.py +10 -0
- package/templates/code/model_handler.py +387 -0
- package/templates/code/serve +300 -0
- package/templates/code/serve.py +175 -0
- package/templates/code/serving.properties +105 -0
- package/templates/code/start_server.py +39 -0
- package/templates/code/start_server.sh +39 -0
- package/templates/diffusors/Dockerfile +72 -0
- package/templates/diffusors/patch_image_api.py +35 -0
- package/templates/diffusors/serve +115 -0
- package/templates/diffusors/start_server.sh +114 -0
- package/templates/do/.gitkeep +1 -0
- package/templates/do/README.md +541 -0
- package/templates/do/build +83 -0
- package/templates/do/ci +681 -0
- package/templates/do/clean +811 -0
- package/templates/do/config +260 -0
- package/templates/do/deploy +1560 -0
- package/templates/do/export +306 -0
- package/templates/do/logs +319 -0
- package/templates/do/manifest +12 -0
- package/templates/do/push +119 -0
- package/templates/do/register +580 -0
- package/templates/do/run +113 -0
- package/templates/do/submit +417 -0
- package/templates/do/test +1147 -0
- package/templates/hyperpod/configmap.yaml +24 -0
- package/templates/hyperpod/deployment.yaml +71 -0
- package/templates/hyperpod/pvc.yaml +42 -0
- package/templates/hyperpod/service.yaml +17 -0
- package/templates/nginx-diffusors.conf +74 -0
- package/templates/nginx-predictors.conf +47 -0
- package/templates/nginx-tensorrt.conf +74 -0
- package/templates/requirements.txt +61 -0
- package/templates/sample_model/test_inference.py +123 -0
- package/templates/sample_model/train_abalone.py +252 -0
- package/templates/test/test_endpoint.sh +79 -0
- package/templates/test/test_local_image.sh +80 -0
- package/templates/test/test_model_handler.py +180 -0
- package/templates/triton/Dockerfile +128 -0
- package/templates/triton/config.pbtxt +163 -0
- package/templates/triton/model.py +130 -0
- package/templates/triton/requirements.txt +11 -0
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* CI Stage Helpers
|
|
6
|
+
*
|
|
7
|
+
* Extracted logic from the CodeBuild buildspec and `do/ci` bash templates
|
|
8
|
+
* into testable JavaScript functions. These functions mirror the bash
|
|
9
|
+
* implementations for stage result parsing, skip logic, error summary
|
|
10
|
+
* extraction, and structure validation.
|
|
11
|
+
*
|
|
12
|
+
* Used by unit and property-based tests to validate CI stage result
|
|
13
|
+
* behavior without executing the bash template directly.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* The ordered list of lifecycle stages executed in CodeBuild.
|
|
18
|
+
*/
|
|
19
|
+
export const STAGE_ORDER = [
|
|
20
|
+
'generate',
|
|
21
|
+
'validate',
|
|
22
|
+
'build',
|
|
23
|
+
'deploy_test',
|
|
24
|
+
'register',
|
|
25
|
+
'teardown',
|
|
26
|
+
'update'
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Stages that always execute regardless of prior failures.
|
|
31
|
+
* Teardown cleans up resources; Update writes results to DynamoDB.
|
|
32
|
+
*/
|
|
33
|
+
export const ALWAYS_RUN_STAGES = ['teardown', 'update']
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Parse a DynamoDB-format stageResults map into plain JavaScript objects.
|
|
37
|
+
*
|
|
38
|
+
* DynamoDB maps use typed descriptors like { S: "pass" }, { N: "12" }.
|
|
39
|
+
* This function converts them to plain values.
|
|
40
|
+
*
|
|
41
|
+
* @param {object} stageResultsMap - DynamoDB map format, e.g.
|
|
42
|
+
* { generate: { M: { status: { S: "pass" }, durationSeconds: { N: "12" }, ... } } }
|
|
43
|
+
* @returns {object} Plain object, e.g.
|
|
44
|
+
* { generate: { status: "pass", durationSeconds: 12, logPointer: "...", errorSummary: "" } }
|
|
45
|
+
*/
|
|
46
|
+
export function parseStageResults(stageResultsMap) {
|
|
47
|
+
if (!stageResultsMap || typeof stageResultsMap !== 'object') {
|
|
48
|
+
return {}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const result = {}
|
|
52
|
+
|
|
53
|
+
for (const [stageName, stageValue] of Object.entries(stageResultsMap)) {
|
|
54
|
+
// Handle DynamoDB M (map) wrapper
|
|
55
|
+
const inner = stageValue && stageValue.M ? stageValue.M : stageValue
|
|
56
|
+
|
|
57
|
+
if (!inner || typeof inner !== 'object') {
|
|
58
|
+
result[stageName] = {
|
|
59
|
+
status: 'unknown',
|
|
60
|
+
durationSeconds: 0,
|
|
61
|
+
logPointer: '',
|
|
62
|
+
errorSummary: ''
|
|
63
|
+
}
|
|
64
|
+
continue
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
result[stageName] = {
|
|
68
|
+
status: extractString(inner.status, 'unknown'),
|
|
69
|
+
durationSeconds: extractNumber(inner.durationSeconds, 0),
|
|
70
|
+
logPointer: extractString(inner.logPointer, ''),
|
|
71
|
+
errorSummary: extractString(inner.errorSummary, '')
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return result
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Compute the overall test status from parsed stage results.
|
|
80
|
+
*
|
|
81
|
+
* Returns 'pass' if all stages passed or were skipped.
|
|
82
|
+
* Returns 'fail-{stageName}' where stageName is the first failing stage
|
|
83
|
+
* in execution order.
|
|
84
|
+
*
|
|
85
|
+
* @param {object} stageResults - Parsed stage results (plain objects)
|
|
86
|
+
* @returns {string} 'pass' or 'fail-{first failing stage}'
|
|
87
|
+
*/
|
|
88
|
+
export function computeTestStatus(stageResults) {
|
|
89
|
+
if (!stageResults || typeof stageResults !== 'object') {
|
|
90
|
+
return 'pass'
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
for (const stage of STAGE_ORDER) {
|
|
94
|
+
const result = stageResults[stage]
|
|
95
|
+
if (result && result.status === 'fail') {
|
|
96
|
+
return `fail-${stage}`
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return 'pass'
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Apply skip logic to stage results after a failure.
|
|
105
|
+
*
|
|
106
|
+
* When a stage fails, all subsequent stages (except teardown and update)
|
|
107
|
+
* are marked as 'skip' with durationSeconds=0. Teardown and update
|
|
108
|
+
* always execute.
|
|
109
|
+
*
|
|
110
|
+
* @param {object} stageResults - Mutable parsed stage results object
|
|
111
|
+
* @param {string} failedStage - The name of the stage that failed
|
|
112
|
+
* @returns {object} The modified stageResults (same reference)
|
|
113
|
+
*/
|
|
114
|
+
export function applySkipLogic(stageResults, failedStage) {
|
|
115
|
+
if (!failedStage || !stageResults) {
|
|
116
|
+
return stageResults || {}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const failedIndex = STAGE_ORDER.indexOf(failedStage)
|
|
120
|
+
if (failedIndex === -1) {
|
|
121
|
+
return stageResults
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Skip all stages after the failed one, except always-run stages
|
|
125
|
+
for (let i = failedIndex + 1; i < STAGE_ORDER.length; i++) {
|
|
126
|
+
const stage = STAGE_ORDER[i]
|
|
127
|
+
if (ALWAYS_RUN_STAGES.includes(stage)) {
|
|
128
|
+
continue
|
|
129
|
+
}
|
|
130
|
+
stageResults[stage] = {
|
|
131
|
+
status: 'skip',
|
|
132
|
+
durationSeconds: 0,
|
|
133
|
+
logPointer: '',
|
|
134
|
+
errorSummary: ''
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return stageResults
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Validate that a stageResults object has the correct structure.
|
|
143
|
+
*
|
|
144
|
+
* A valid stageResults map must contain exactly 7 entries (one per
|
|
145
|
+
* lifecycle stage) and each entry must have the required fields:
|
|
146
|
+
* status, durationSeconds, logPointer.
|
|
147
|
+
*
|
|
148
|
+
* @param {object} stageResults - Parsed stage results to validate
|
|
149
|
+
* @returns {object} Validation result
|
|
150
|
+
* @returns {boolean} return.valid - Whether the structure is valid
|
|
151
|
+
* @returns {string[]} return.errors - Array of validation error messages
|
|
152
|
+
*/
|
|
153
|
+
export function validateStageResultStructure(stageResults) {
|
|
154
|
+
const errors = []
|
|
155
|
+
|
|
156
|
+
if (!stageResults || typeof stageResults !== 'object') {
|
|
157
|
+
return { valid: false, errors: ['stageResults is null or not an object'] }
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const stageKeys = Object.keys(stageResults)
|
|
161
|
+
|
|
162
|
+
// Check for exactly 7 entries
|
|
163
|
+
if (stageKeys.length !== 7) {
|
|
164
|
+
errors.push(`Expected 7 stage entries, found ${stageKeys.length}`)
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Check all required stages are present
|
|
168
|
+
for (const stage of STAGE_ORDER) {
|
|
169
|
+
if (!(stage in stageResults)) {
|
|
170
|
+
errors.push(`Missing required stage: ${stage}`)
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Check for unexpected stages
|
|
175
|
+
for (const key of stageKeys) {
|
|
176
|
+
if (!STAGE_ORDER.includes(key)) {
|
|
177
|
+
errors.push(`Unexpected stage: ${key}`)
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Validate each stage entry has required fields
|
|
182
|
+
for (const stage of STAGE_ORDER) {
|
|
183
|
+
const entry = stageResults[stage]
|
|
184
|
+
if (!entry) continue
|
|
185
|
+
|
|
186
|
+
if (!('status' in entry)) {
|
|
187
|
+
errors.push(`Stage '${stage}' missing required field: status`)
|
|
188
|
+
} else if (!['pass', 'fail', 'skip'].includes(entry.status)) {
|
|
189
|
+
errors.push(`Stage '${stage}' has invalid status: '${entry.status}'`)
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (!('durationSeconds' in entry)) {
|
|
193
|
+
errors.push(`Stage '${stage}' missing required field: durationSeconds`)
|
|
194
|
+
} else if (typeof entry.durationSeconds !== 'number' || entry.durationSeconds < 0) {
|
|
195
|
+
errors.push(`Stage '${stage}' has invalid durationSeconds: ${entry.durationSeconds}`)
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
if (!('logPointer' in entry)) {
|
|
199
|
+
errors.push(`Stage '${stage}' missing required field: logPointer`)
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// errorSummary is required when status is 'fail'
|
|
203
|
+
if (entry.status === 'fail' && !('errorSummary' in entry)) {
|
|
204
|
+
errors.push(`Stage '${stage}' has status 'fail' but missing errorSummary`)
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// errorSummary must be at most 500 characters
|
|
208
|
+
if (entry.errorSummary && entry.errorSummary.length > 500) {
|
|
209
|
+
errors.push(`Stage '${stage}' errorSummary exceeds 500 characters (${entry.errorSummary.length})`)
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
return { valid: errors.length === 0, errors }
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Extract error summaries from stage results for display.
|
|
218
|
+
*
|
|
219
|
+
* Returns an array of { stage, errorSummary } for all stages that failed.
|
|
220
|
+
*
|
|
221
|
+
* @param {object} stageResults - Parsed stage results
|
|
222
|
+
* @returns {object[]} Array of { stage: string, errorSummary: string }
|
|
223
|
+
*/
|
|
224
|
+
export function extractErrorSummaries(stageResults) {
|
|
225
|
+
if (!stageResults || typeof stageResults !== 'object') {
|
|
226
|
+
return []
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
const summaries = []
|
|
230
|
+
for (const stage of STAGE_ORDER) {
|
|
231
|
+
const entry = stageResults[stage]
|
|
232
|
+
if (entry && entry.status === 'fail' && entry.errorSummary) {
|
|
233
|
+
summaries.push({
|
|
234
|
+
stage,
|
|
235
|
+
errorSummary: entry.errorSummary
|
|
236
|
+
})
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
return summaries
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// --- Internal helpers ---
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Extract a string value from a DynamoDB typed descriptor or plain value.
|
|
246
|
+
* @param {*} value - Either { S: "string" } or a plain string
|
|
247
|
+
* @param {string} defaultValue - Default if value is missing
|
|
248
|
+
* @returns {string}
|
|
249
|
+
*/
|
|
250
|
+
function extractString(value, defaultValue) {
|
|
251
|
+
if (value === undefined || value === null) return defaultValue
|
|
252
|
+
if (typeof value === 'string') return value
|
|
253
|
+
if (value.S !== undefined) return value.S
|
|
254
|
+
return defaultValue
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Extract a number value from a DynamoDB typed descriptor or plain value.
|
|
259
|
+
* @param {*} value - Either { N: "12" } or a plain number
|
|
260
|
+
* @param {number} defaultValue - Default if value is missing
|
|
261
|
+
* @returns {number}
|
|
262
|
+
*/
|
|
263
|
+
function extractNumber(value, defaultValue) {
|
|
264
|
+
if (value === undefined || value === null) return defaultValue
|
|
265
|
+
if (typeof value === 'number') return value
|
|
266
|
+
if (value.N !== undefined) return Number(value.N)
|
|
267
|
+
return defaultValue
|
|
268
|
+
}
|