@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.
Files changed (143) hide show
  1. package/LICENSE +202 -0
  2. package/LICENSE-THIRD-PARTY +68620 -0
  3. package/NOTICE +2 -0
  4. package/README.md +106 -0
  5. package/bin/cli.js +365 -0
  6. package/config/defaults.json +32 -0
  7. package/config/presets/transformers-djl.json +26 -0
  8. package/config/presets/transformers-gpu.json +24 -0
  9. package/config/presets/transformers-lmi.json +27 -0
  10. package/package.json +129 -0
  11. package/servers/README.md +419 -0
  12. package/servers/base-image-picker/catalogs/model-servers.json +1191 -0
  13. package/servers/base-image-picker/catalogs/python-slim.json +38 -0
  14. package/servers/base-image-picker/catalogs/triton-backends.json +51 -0
  15. package/servers/base-image-picker/catalogs/triton.json +38 -0
  16. package/servers/base-image-picker/index.js +495 -0
  17. package/servers/base-image-picker/manifest.json +17 -0
  18. package/servers/base-image-picker/package.json +15 -0
  19. package/servers/hyperpod-cluster-picker/LICENSE +202 -0
  20. package/servers/hyperpod-cluster-picker/index.js +424 -0
  21. package/servers/hyperpod-cluster-picker/manifest.json +14 -0
  22. package/servers/hyperpod-cluster-picker/package.json +17 -0
  23. package/servers/instance-recommender/LICENSE +202 -0
  24. package/servers/instance-recommender/catalogs/instances.json +852 -0
  25. package/servers/instance-recommender/index.js +284 -0
  26. package/servers/instance-recommender/manifest.json +16 -0
  27. package/servers/instance-recommender/package.json +15 -0
  28. package/servers/lib/LICENSE +202 -0
  29. package/servers/lib/bedrock-client.js +160 -0
  30. package/servers/lib/custom-validators.js +46 -0
  31. package/servers/lib/dynamic-resolver.js +36 -0
  32. package/servers/lib/package.json +11 -0
  33. package/servers/lib/schemas/image-catalog.schema.json +185 -0
  34. package/servers/lib/schemas/instances.schema.json +124 -0
  35. package/servers/lib/schemas/manifest.schema.json +64 -0
  36. package/servers/lib/schemas/model-catalog.schema.json +91 -0
  37. package/servers/lib/schemas/regions.schema.json +26 -0
  38. package/servers/lib/schemas/triton-backends.schema.json +51 -0
  39. package/servers/model-picker/catalogs/jumpstart-public.json +66 -0
  40. package/servers/model-picker/catalogs/popular-diffusors.json +88 -0
  41. package/servers/model-picker/catalogs/popular-transformers.json +226 -0
  42. package/servers/model-picker/index.js +1693 -0
  43. package/servers/model-picker/manifest.json +18 -0
  44. package/servers/model-picker/package.json +20 -0
  45. package/servers/region-picker/LICENSE +202 -0
  46. package/servers/region-picker/catalogs/regions.json +263 -0
  47. package/servers/region-picker/index.js +230 -0
  48. package/servers/region-picker/manifest.json +16 -0
  49. package/servers/region-picker/package.json +15 -0
  50. package/src/app.js +1007 -0
  51. package/src/copy-tpl.js +77 -0
  52. package/src/lib/accelerator-validator.js +39 -0
  53. package/src/lib/asset-manager.js +385 -0
  54. package/src/lib/aws-profile-parser.js +181 -0
  55. package/src/lib/bootstrap-command-handler.js +1647 -0
  56. package/src/lib/bootstrap-config.js +238 -0
  57. package/src/lib/ci-register-helpers.js +124 -0
  58. package/src/lib/ci-report-helpers.js +158 -0
  59. package/src/lib/ci-stage-helpers.js +268 -0
  60. package/src/lib/cli-handler.js +529 -0
  61. package/src/lib/comment-generator.js +544 -0
  62. package/src/lib/community-reports-validator.js +91 -0
  63. package/src/lib/config-manager.js +2106 -0
  64. package/src/lib/configuration-exporter.js +204 -0
  65. package/src/lib/configuration-manager.js +695 -0
  66. package/src/lib/configuration-matcher.js +221 -0
  67. package/src/lib/cpu-validator.js +36 -0
  68. package/src/lib/cuda-validator.js +57 -0
  69. package/src/lib/deployment-config-resolver.js +103 -0
  70. package/src/lib/deployment-entry-schema.js +125 -0
  71. package/src/lib/deployment-registry.js +598 -0
  72. package/src/lib/docker-introspection-validator.js +51 -0
  73. package/src/lib/engine-prefix-resolver.js +60 -0
  74. package/src/lib/huggingface-client.js +172 -0
  75. package/src/lib/key-value-parser.js +37 -0
  76. package/src/lib/known-flags-validator.js +200 -0
  77. package/src/lib/manifest-cli.js +280 -0
  78. package/src/lib/mcp-client.js +303 -0
  79. package/src/lib/mcp-command-handler.js +532 -0
  80. package/src/lib/neuron-validator.js +80 -0
  81. package/src/lib/parameter-schema-validator.js +284 -0
  82. package/src/lib/prompt-runner.js +1349 -0
  83. package/src/lib/prompts.js +1138 -0
  84. package/src/lib/registry-command-handler.js +519 -0
  85. package/src/lib/registry-loader.js +198 -0
  86. package/src/lib/rocm-validator.js +80 -0
  87. package/src/lib/schema-validator.js +157 -0
  88. package/src/lib/sensitive-redactor.js +59 -0
  89. package/src/lib/template-engine.js +156 -0
  90. package/src/lib/template-manager.js +341 -0
  91. package/src/lib/validation-engine.js +314 -0
  92. package/src/prompt-adapter.js +63 -0
  93. package/templates/Dockerfile +300 -0
  94. package/templates/IAM_PERMISSIONS.md +84 -0
  95. package/templates/MIGRATION.md +488 -0
  96. package/templates/PROJECT_README.md +439 -0
  97. package/templates/TEMPLATE_SYSTEM.md +243 -0
  98. package/templates/buildspec.yml +64 -0
  99. package/templates/code/chat_template.jinja +1 -0
  100. package/templates/code/flask/gunicorn_config.py +35 -0
  101. package/templates/code/flask/wsgi.py +10 -0
  102. package/templates/code/model_handler.py +387 -0
  103. package/templates/code/serve +300 -0
  104. package/templates/code/serve.py +175 -0
  105. package/templates/code/serving.properties +105 -0
  106. package/templates/code/start_server.py +39 -0
  107. package/templates/code/start_server.sh +39 -0
  108. package/templates/diffusors/Dockerfile +72 -0
  109. package/templates/diffusors/patch_image_api.py +35 -0
  110. package/templates/diffusors/serve +115 -0
  111. package/templates/diffusors/start_server.sh +114 -0
  112. package/templates/do/.gitkeep +1 -0
  113. package/templates/do/README.md +541 -0
  114. package/templates/do/build +83 -0
  115. package/templates/do/ci +681 -0
  116. package/templates/do/clean +811 -0
  117. package/templates/do/config +260 -0
  118. package/templates/do/deploy +1560 -0
  119. package/templates/do/export +306 -0
  120. package/templates/do/logs +319 -0
  121. package/templates/do/manifest +12 -0
  122. package/templates/do/push +119 -0
  123. package/templates/do/register +580 -0
  124. package/templates/do/run +113 -0
  125. package/templates/do/submit +417 -0
  126. package/templates/do/test +1147 -0
  127. package/templates/hyperpod/configmap.yaml +24 -0
  128. package/templates/hyperpod/deployment.yaml +71 -0
  129. package/templates/hyperpod/pvc.yaml +42 -0
  130. package/templates/hyperpod/service.yaml +17 -0
  131. package/templates/nginx-diffusors.conf +74 -0
  132. package/templates/nginx-predictors.conf +47 -0
  133. package/templates/nginx-tensorrt.conf +74 -0
  134. package/templates/requirements.txt +61 -0
  135. package/templates/sample_model/test_inference.py +123 -0
  136. package/templates/sample_model/train_abalone.py +252 -0
  137. package/templates/test/test_endpoint.sh +79 -0
  138. package/templates/test/test_local_image.sh +80 -0
  139. package/templates/test/test_model_handler.py +180 -0
  140. package/templates/triton/Dockerfile +128 -0
  141. package/templates/triton/config.pbtxt +163 -0
  142. package/templates/triton/model.py +130 -0
  143. 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
+ }