11# -*- coding: utf-8 -*-
22"""``deployments`` sub-command group."""
33import time
4+ from http import HTTPStatus
45from typing import Optional
56
67import typer
1213 console ,
1314 err_console ,
1415 ensure_ok ,
16+ error ,
1517 handle_sdk_error ,
1618 logger ,
19+ print_failed_message ,
1720 success ,
1821)
1922
@@ -37,12 +40,34 @@ def callback(ctx: typer.Context):
3740# ---------------------------------------------------------------------------
3841
3942
40- def _wait_for_deployment (deployed_model : str ):
41- """Block until the deployment reaches a non-pending state."""
43+ # ---------------------------------------------------------------------------
44+ # Constants
45+ # ---------------------------------------------------------------------------
46+ DEFAULT_WAIT_TIMEOUT = 3600 # 1 hour default timeout for waiting
47+
48+
49+ def _wait_for_deployment (
50+ deployed_model : str ,
51+ timeout : int = DEFAULT_WAIT_TIMEOUT ,
52+ ):
53+ """Block until the deployment reaches a non-pending state or times out."""
54+ start_time = time .time ()
4255 try :
4356 while True :
57+ # Check timeout
58+ elapsed = time .time () - start_time
59+ if elapsed > timeout :
60+ err_console .print (
61+ "[red]Timeout:[/red] Deployment "
62+ f"{ deployed_model } did not complete within "
63+ f"{ timeout } seconds. You can check status later via: "
64+ f"[cyan]dashscope deployments get { deployed_model } [/cyan]" ,
65+ )
66+ raise typer .Exit (1 )
67+
4468 rsp = dashscope .Deployments .get (deployed_model )
45- output = ensure_ok (rsp )
69+ # During polling, only check HTTP success, not business errors
70+ output = ensure_ok (rsp , check_business_error = False )
4671 status = output .status
4772
4873 if status in (
@@ -67,7 +92,12 @@ def _wait_for_deployment(deployed_model: str):
6792
6893def _print_deployments (output ):
6994 """Pretty-print a list of deployments from *output*."""
70- if output is None or not output .deployments :
95+ if (
96+ output is None
97+ or not isinstance (output , dict )
98+ or "deployments" not in output
99+ or not output ["deployments" ]
100+ ):
71101 console .print ("There is no deployed model!" )
72102 return
73103 for dep in output .deployments :
@@ -99,15 +129,46 @@ def create(
99129 "--capacity" ,
100130 help = "The target capacity" ,
101131 ),
132+ plan : Optional [str ] = typer .Option (
133+ None ,
134+ "--plan" ,
135+ help = "Deployment plan or template ID" ,
136+ ),
137+ template_id : Optional [str ] = typer .Option (
138+ None ,
139+ "--template-id" ,
140+ help = "Template ID for deployment configuration" ,
141+ ),
102142):
103143 """Create a model deployment."""
104- rsp = dashscope .Deployments .call (
105- model = model ,
106- capacity = capacity ,
107- suffix = suffix , # type: ignore[arg-type]
108- )
109- output = ensure_ok (rsp )
110- deployed_model = output .deployed_model
144+ kwargs = {
145+ "model" : model ,
146+ "capacity" : capacity ,
147+ "suffix" : suffix ,
148+ }
149+ if plan is not None :
150+ kwargs ["plan" ] = plan
151+ if template_id is not None :
152+ kwargs ["template_id" ] = template_id
153+
154+ rsp = dashscope .Deployments .call (** kwargs )
155+
156+ # Enhanced error checking: verify both HTTP status and response content
157+ if rsp .status_code != HTTPStatus .OK :
158+ print_failed_message (rsp )
159+ raise typer .Exit (1 )
160+
161+ output = rsp .output
162+ if output is None :
163+ error ("Deployment creation returned empty response" )
164+
165+ deployed_model = output .get ("deployed_model" )
166+ if not deployed_model :
167+ error (
168+ "Deployment creation succeeded but missing deployed_model "
169+ f"in response. Response: { output } " ,
170+ )
171+
111172 success (f"Create model: { deployed_model } deployment" )
112173 _wait_for_deployment (deployed_model )
113174
0 commit comments