Repository navigation
fix(serve): Support pipeline variable image_uri in ModelBuilder.build - #6347
lucasjia-aws merged 1 commit into
Conversation
ModelBuilder.image_uri is typed Optional[StrPipeVar], but build() treated it as a plain string in two places, so a ParameterString image failed under a PipelineSession: - is_1p_image_uri() sliced the value (image_uri[0:12]), raising "'ParameterString' object is not subscriptable" in _build_validations. - _create_sagemaker_model() ran "nova-" in image_uri for the Nova network-isolation default, raising "argument of type 'ParameterString' is not iterable". A pipeline variable is only resolved at execution time, so is_1p_image_uri() now treats non-string values as not first-party, and the Nova network-isolation check only inspects string images. The pipeline variable is passed through unchanged to CreateModel. Fixes aws#5760
|
Claude finished @lucasjia-aws's task in 1m 22s —— View job ReviewI reviewed the diff against (Note: the inline-comment tool isn't available in this run, so findings are consolidated here with file/line references.) Correctness ✅
Types
Tests ✅
Minor observations (non-blocking)
No security or performance concerns; the change removes failure modes rather than adding surface area, and adheres to the repo's v3-by-default guidance (all examples/tests use |
mohamedzeidan2021
left a comment
There was a problem hiding this comment.
Approving. Reproduced TypeError: 'ParameterString' object is not subscriptable on master and its absence after, plus end-to-end through ModelStep + Pipeline.definition() correctly rendering {"Get": "Parameters.ServingImageUri"}, and adversarially across Join, ExecutionVariable, Properties, and a ParameterString whose default value is itself a 1P image (correctly not consulted). All 7 new tests fail on reverted source. The unit-test diff is decisive: 26 failures pre-fix vs 23 post-fix, with the 23 an identical set — no regressions.
Skip is the right semantics, and I checked the alternatives rather than taking it on faith. Deferring resolution is impossible: EnableNetworkIsolation is a static boolean baked into the pipeline definition at definition time, while the image string only exists at execution time, so there's no expression form for "1P-ness of the resolved image". Erroring would break the legitimate case the issue asks for. I also confirmed the skip is a genuine no-op on the passthrough path — 1P and 3P literal images produce byte-identical CreateModel requests, because both branches set _passthrough = True and return.
The #5910 comparison holds up: restoring only check_image_uri.py still fails at the Nova check with TypeError: argument of type 'ParameterString' is not iterable, so this PR's claim that #5910 is insufficient is independently verified. Nothing of substance is lost — the only thing #5910 had that this drops is hardening of validate_image_uri_and_hardware, which has zero src/ callers. (Minor correction for the record: #5910 was authored by sagemaker-bot, not a community contributor, so no human attribution is owed.)
One request I'd like before merge, not blocking this approval: the Nova network-isolation default is now silently skipped for a pipeline-variable image, with only an internal code comment. Nova 1P account IDs are region-specific, so parameterising the image to switch regions is realistic, and ModelBuilder(image_uri=ParameterString(...)) with a Nova default yields a definition with no EnableNetworkIsolation where the literal yields True — the user finds out at pipeline execution time. A one-line logger.warning when the image is a pipeline variable and _enable_network_isolation is unset would close it, matching the existing convention around model_builder.py:2726 for pipeline-variable model_data.
Two smaller notes: consider using the already-imported is_pipeline_variable() (line 152, used at 2675/2726/2895/2911, and the same guard sagemaker-core uses in fw_utils.py/common_utils.py) instead of hand-rolled isinstance(x, str) — functionally a superset so there's no bug, but it diverges from convention and silently reclassifies genuinely wrong types (None, an int, a Model) from fail-fast to "not 1P". And there's no guard for a pipeline-variable image_uri under a non-PipelineSession, where the user now gets an opaque __str__ failure deep inside botocore instead of the old clear TypeError; model_builder.py:2727 has the established warn-pattern for that.
Issue
Fixes #5760. Supersedes #5910.
Problem
ModelBuilder.build()fails whenimage_uriis a pipeline variable such asParameterStringunder aPipelineSession, even thoughModelBuilder.image_uriis typedOptional[StrPipeVar]. This blocks V2 -> V3 pipeline migrations that parameterize the serving image.Root cause
The build path treats
image_urias a plain string in two places. First,_build_validationscallsis_1p_image_uri(self.image_uri), which slices the value withimage_uri[0:12]and raisesTypeError: 'ParameterString' object is not subscriptable(the error in the issue). Second, once that is fixed,_create_sagemaker_modelevaluates"nova-" in resolved_image_urifor the Nova network-isolation default and raisesTypeError: argument of type 'ParameterString' is not iterable.PipelineVariableintentionally defines neither__getitem__nor__contains__, and its__str__raises.#5910 only addresses the first failure, so the reporter's snippet still fails with it applied.
Fix
is_1p_image_urireturnsFalsefor any non-string value. A pipeline variable is only resolved at execution time, so its account cannot be inspected at build time. On the image-only passthrough path both branches of_build_validationslead to passthrough, so the result is unchanged; with amodeland nomodel_server, users now get the existing "Model_server must be set" error instead of aTypeError._create_sagemaker_modelonly inspects string images. For a pipeline-variable image, setenable_network_isolationexplicitly if needed."Image": {"Get": "Parameters.<name>"}.Testing
tests/unit/test_model_builder_pipeline_variable_image_uri.py:_build_validationspassthrough and model_server cases, the_create_sagemaker_modelnetwork-isolation check with a pipeline-variable image and a Nova 1P string image (regression guard), and an end-to-endbuild()under a realPipelineSessionasserting theCreateModelrequest keeps theParameterString.tests/unit/validations/test_check_image_uri.py:ParameterString(with a 1P default value),Join, andNoneinputs.sagemaker-serveunit test failure set is identical before and after the change.ModelStepbuilt from the result produces a pipeline definition with the parameterized image.