@@ -56,6 +56,23 @@ def _CreateAgentEngineSandboxConfig_to_vertex(
5656 if getv (from_object , ["ttl" ]) is not None :
5757 setv (parent_object , ["ttl" ], getv (from_object , ["ttl" ]))
5858
59+ if getv (from_object , ["sandbox_environment_template" ]) is not None :
60+ setv (
61+ parent_object ,
62+ ["sandboxEnvironmentTemplate" ],
63+ getv (from_object , ["sandbox_environment_template" ]),
64+ )
65+
66+ if getv (from_object , ["sandbox_environment_snapshot" ]) is not None :
67+ setv (
68+ parent_object ,
69+ ["sandboxEnvironmentSnapshot" ],
70+ getv (from_object , ["sandbox_environment_snapshot" ]),
71+ )
72+
73+ if getv (from_object , ["owner" ]) is not None :
74+ setv (parent_object , ["owner" ], getv (from_object , ["owner" ]))
75+
5976 return to_object
6077
6178
@@ -837,7 +854,7 @@ def delete(
837854 def generate_access_token (
838855 self ,
839856 service_account_email : str ,
840- sandbox_id : str ,
857+ sandbox_hostname : str ,
841858 port : str = "8080" ,
842859 timeout : int = 3600 ,
843860 ) -> str :
@@ -846,8 +863,8 @@ def generate_access_token(
846863 Args:
847864 service_account_email (str):
848865 Required. The email of the service account to use for signing.
849- sandbox_id (str):
850- Required. The resource name of the sandbox to generate a token for.
866+ sandbox_hostname (str):
867+ Required. The hostname of the sandbox to generate a token for.
851868 port (str):
852869 Optional. The port to use for the token. Defaults to "8080".
853870 timeout (int):
@@ -858,13 +875,14 @@ def generate_access_token(
858875 """
859876 client = iam_credentials_v1 .IAMCredentialsClient ()
860877 name = f"projects/-/serviceAccounts/{ service_account_email } "
861- custom_claims = {"port " : port , "sandbox_id " : sandbox_id }
878+ custom_claims = {"hostname " : sandbox_hostname , "port " : port }
862879 payload = {
863880 "iat" : int (time .time ()),
864881 "exp" : int (time .time ()) + timeout ,
865882 "iss" : service_account_email ,
883+ "sub" : service_account_email ,
866884 "nonce" : secrets .randbelow (1000000000 ) + 1 ,
867- "aud" : "vmaas-proxy-api " , # default audience for sandbox proxy
885+ "aud" : "https://aiplatform.googleapis.com/ " , # default audience for sandbox proxy
868886 ** custom_claims ,
869887 }
870888 request = iam_credentials_v1 .SignJwtRequest (
@@ -880,6 +898,7 @@ def send_command(
880898 http_method : str ,
881899 access_token : str ,
882900 sandbox_environment : types .SandboxEnvironment ,
901+ port : str = "8080" ,
883902 path : Optional [str ] = None ,
884903 query_params : Optional [dict [str , object ]] = None ,
885904 headers : Optional [dict [str , str ]] = None ,
@@ -894,6 +913,8 @@ def send_command(
894913 Required. The access token to use for authorization.
895914 sandbox_environment (types.SandboxEnvironment):
896915 Required. The sandbox environment to send the command to.
916+ port (str):
917+ Optional. The port to use for the token. Defaults to "8080". This should be one of the ports specified during template creation.
897918 path (str):
898919 Optional. The path to send the command to.
899920 query_params (dict[str, object]):
@@ -918,10 +939,14 @@ def send_command(
918939 else :
919940 raise ValueError ("Load balancer hostname or ip is not available." )
920941
942+ routing_token = connection_info .routing_token
943+
921944 path = path or ""
922945 if query_params :
923946 path = f"{ path } ?{ urlencode (query_params )} "
924947 headers ["Authorization" ] = f"Bearer { access_token } "
948+ headers ["X-Sandbox-Routing-Token" ] = routing_token
949+ headers ["X-Sandbox-Port" ] = port
925950 endpoint = endpoint + path if path .startswith ("/" ) else endpoint + "/" + path
926951 http_options = genai_types .HttpOptions (headers = headers , base_url = endpoint )
927952 http_client = genai .Client (vertexai = True , http_options = http_options )
@@ -937,6 +962,7 @@ def generate_browser_ws_headers(
937962 self ,
938963 sandbox_environment : types .SandboxEnvironment ,
939964 service_account_email : str ,
965+ port : str = "8080" ,
940966 timeout : int = 3600 ,
941967 ) -> tuple [str , dict [str , str ]]:
942968 """Generates the websocket upgrade headers for the browser.
@@ -946,47 +972,59 @@ def generate_browser_ws_headers(
946972 Required. The sandbox environment to generate websocket headers for.
947973 service_account_email (str):
948974 Required. The email of the service account to use for signing.
975+ port (str):
976+ Optional. The port to use for the token. Defaults to "8080". This
977+ should be one of the ports specified during template creation.
949978 timeout (int):
950979 Optional. The timeout in seconds for the token. Defaults to 3600.
951980
952981 Returns:
953982 tuple[str, dict[str, str]]: A tuple containing the websocket URL and
954983 the headers for websocket upgrade.
955984 """
956- sandbox_id = sandbox_environment .name
985+ if not sandbox_environment .connection_info :
986+ raise ValueError ("Connection info is not available." )
987+
988+ ws_url = "wss://test-us-central1.autopush-sandbox.vertexai.goog"
989+ connection_info = sandbox_environment .connection_info
990+ if connection_info .load_balancer_hostname :
991+ ws_base_url = "wss://" + connection_info .load_balancer_hostname
992+ elif connection_info .load_balancer_ip :
993+ ws_base_url = "ws://" + connection_info .load_balancer_ip
994+ else :
995+ raise ValueError ("Load balancer hostname or ip is not available." )
996+
957997 # port 8080 is the default port for http endpoint.
958998 http_access_token = self .generate_access_token (
959- service_account_email , sandbox_id , "8080" , timeout
999+ service_account_email , connection_info . load_balancer_hostname , port , timeout
9601000 )
9611001 response = self .send_command (
9621002 http_method = "GET" ,
9631003 access_token = http_access_token ,
9641004 sandbox_environment = sandbox_environment ,
1005+ port = port ,
9651006 path = "/cdp_ws_endpoint" ,
9661007 )
9671008 if not response :
9681009 raise ValueError ("Failed to get the websocket endpoint." )
9691010 body_dict = json .loads (response .body )
9701011 ws_path = body_dict ["endpoint" ]
971-
972- ws_url = "wss://test-us-central1.autopush-sandbox.vertexai.goog"
973- if sandbox_environment and sandbox_environment .connection_info :
974- connection_info = sandbox_environment .connection_info
975- if connection_info .load_balancer_hostname :
976- ws_url = "wss://" + connection_info .load_balancer_hostname
977- elif connection_info .load_balancer_ip :
978- ws_url = "ws://" + connection_info .load_balancer_ip
979- else :
980- raise ValueError ("Load balancer hostname or ip is not available." )
981- ws_url = ws_url + "/" + ws_path
1012+ ws_url = ws_base_url + "/" + ws_path
9821013
9831014 # port 9222 is the default port for the browser websocket endpoint.
9841015 ws_access_token = self .generate_access_token (
985- service_account_email , sandbox_id , "9222" , timeout
1016+ service_account_email ,
1017+ connection_info .load_balancer_hostname ,
1018+ "9222" ,
1019+ timeout ,
9861020 )
9871021
1022+ routing_token = connection_info .routing_token
1023+
9881024 headers = {}
989- headers ["Sec-WebSocket-Protocol" ] = f"binary, { ws_access_token } "
1025+ headers ["Sec-WebSocket-Protocol" ] = (
1026+ f"v1.stream, { ws_access_token } , { routing_token } , { port } "
1027+ )
9901028 return ws_url , headers
9911029
9921030
0 commit comments