11# eval_protocol/platform_api.py
22import logging
33import sys
4- from typing import Any , Dict , Optional
4+ from typing import Optional
55
6- import requests
76from dotenv import find_dotenv , load_dotenv
87
98from eval_protocol .auth import (
109 get_fireworks_account_id ,
1110 get_fireworks_api_base ,
1211 get_fireworks_api_key ,
1312)
14- from eval_protocol .common_utils import get_user_agent
13+ from fireworks .types import Secret
14+ from fireworks import Fireworks , FireworksError , NotFoundError , InternalServerError
1515
1616logger = logging .getLogger (__name__ )
1717
@@ -88,47 +88,31 @@ def create_or_update_fireworks_secret(
8888 resolved_api_key = api_key or get_fireworks_api_key ()
8989 resolved_api_base = api_base or get_fireworks_api_base ()
9090 resolved_account_id = account_id # Must be provided
91+ client = Fireworks (api_key = resolved_api_key , account_id = resolved_account_id , base_url = resolved_api_base )
9192
9293 if not all ([resolved_api_key , resolved_api_base , resolved_account_id ]):
9394 logger .error ("Missing Fireworks API key, base URL, or account ID for creating/updating secret." )
9495 return False
9596
96- headers = {
97- "Authorization" : f"Bearer { resolved_api_key } " ,
98- "Content-Type" : "application/json" ,
99- "User-Agent" : get_user_agent (),
100- }
101-
102- # The secret_id for GET/PATCH/DELETE operations is the key_name.
103- # The 'name' field in the gatewaySecret model for POST/PATCH is a bit ambiguous.
104- # For POST (create), the body is gatewaySecret, which has 'name', 'keyName', 'value'.
105- # 'name' in POST body is likely just the 'keyName' or 'secret_id' for creation context,
106- # as the full resource name 'accounts/.../secrets/...' is server-generated.
107- # Let's assume for POST, we send 'keyName' and 'value'.
108- # For PATCH, the path contains {secret_id} which is the key_name. The body is also gatewaySecret.
109-
11097 # Check if secret exists using GET (path uses normalized resource id)
11198 resource_id = _normalize_secret_resource_id (key_name )
11299 secret_exists = False
113100 try :
114- url = f"{ resolved_api_base } /v1/accounts/{ resolved_account_id } /secrets/{ resource_id } "
115- response = requests .get (url , headers = headers , timeout = 10 )
116- if response .status_code == 200 :
101+ secret = client .secrets .get (resource_id )
102+ if secret :
117103 secret_exists = True
118104 logger .info (f"Secret '{ key_name } ' already exists. Will attempt to update." )
119- elif response .status_code == 404 :
120- logger .info (f"Secret '{ key_name } ' does not exist. Will attempt to create." )
121- secret_exists = False
122- elif response .status_code == 500 : # As per user feedback, 500 on GET might mean not found
123- logger .warning (
124- f"Received 500 error when checking for secret '{ key_name } '. Assuming it does not exist and will attempt to create. Response: { response .text } "
125- )
126- secret_exists = False
127- else :
128- logger .error (f"Error checking for secret '{ key_name } ': { response .status_code } - { response .text } " )
129- return False
130- except requests .exceptions .RequestException as e :
131- logger .error (f"Request exception while checking for secret '{ key_name } ': { e } " )
105+ except NotFoundError :
106+ # Secret doesn't exist, proceed with creation
107+ secret_exists = False
108+ except InternalServerError as e :
109+ # As per user feedback, 500 on GET might mean not found, treat as not found
110+ logger .warning (
111+ f"Received 500 error when checking for secret '{ key_name } '. Assuming it doesn't exist. Response: { e } "
112+ )
113+ secret_exists = False
114+ except FireworksError as e :
115+ logger .error (f"Error checking for secret '{ key_name } ': { e } " )
132116 return False
133117
134118 if secret_exists :
@@ -144,31 +128,15 @@ def create_or_update_fireworks_secret(
144128 )
145129 payload_key_name = "EP_SECRET" # Fallback, though unlikely needed with .upper()
146130
147- payload = {"keyName" : payload_key_name , "value" : secret_value }
148131 try :
149- logger .debug (f"PATCH payload for '{ key_name } ': { payload } " )
150- url = f"{ resolved_api_base } /v1/accounts/{ resolved_account_id } /secrets/{ resource_id } "
151- response = requests .patch (url , json = payload , headers = headers , timeout = 30 )
152- response .raise_for_status ()
132+ logger .debug (f"PATCH payload for '{ key_name } ': key_name={ payload_key_name } " )
133+ client .secrets .update (resource_id , key_name = payload_key_name , value = secret_value )
153134 logger .info (f"Successfully updated secret '{ key_name } ' on Fireworks platform." )
154135 return True
155- except requests .exceptions .HTTPError as e :
156- logger .error (f"HTTP error updating secret '{ key_name } ': { e .response .status_code } - { e .response .text } " )
157- return False
158- except requests .exceptions .RequestException as e :
159- logger .error (f"Request exception updating secret '{ key_name } ': { e } " )
136+ except FireworksError as e :
137+ logger .error (f"Error updating secret '{ key_name } ': { e } " )
160138 return False
161139 else :
162- # Create new secret (POST)
163- # Body for POST is gatewaySecret. 'name' field in payload is the resource path.
164- # Let's assume for POST, the 'name' in payload can be omitted or is the key_name.
165- # The API should ideally use 'keyName' from URL or a specific 'secretId' in payload for creation if 'name' is server-assigned.
166- # Given the Swagger, 'name' is required in gatewaySecret.
167- # Let's try with 'name' being the 'key_name' for the payload, as the full path is not known yet.
168- # This might need adjustment based on actual API behavior.
169- # Construct the full 'name' path for the POST payload as per Swagger's title for 'name'
170- full_resource_name_for_payload = f"accounts/{ resolved_account_id } /secrets/{ resource_id } "
171-
172140 # Transform key_name for payload "keyName" field: uppercase and underscores
173141 payload_key_name = key_name .upper ().replace ("-" , "_" )
174142 if not payload_key_name or not payload_key_name [0 ].isupper ():
@@ -177,26 +145,12 @@ def create_or_update_fireworks_secret(
177145 )
178146 payload_key_name = "EP_SECRET"
179147
180- payload = {
181- "name" : full_resource_name_for_payload , # This 'name' is the resource path
182- "keyName" : payload_key_name , # This 'keyName' is the specific field with new rules
183- "value" : secret_value ,
184- }
185148 try :
186- logger .debug (f"POST payload for '{ key_name } ': { payload } " )
187- url = f"{ resolved_api_base } /v1/accounts/{ resolved_account_id } /secrets"
188- response = requests .post (url , json = payload , headers = headers , timeout = 30 )
189- response .raise_for_status ()
190- logger .info (
191- f"Successfully created secret '{ key_name } ' on Fireworks platform. Full name: { response .json ().get ('name' )} "
192- )
149+ logger .debug (f"POST payload for '{ key_name } ': { payload_key_name } " )
150+ client .secrets .create (key_name = payload_key_name , value = secret_value , name = resource_id )
193151 return True
194- except requests .exceptions .HTTPError as e :
195- logger .error (f"HTTP error creating secret '{ key_name } ': { e .response .status_code } - { e .response .text } " )
196- # If error is due to 'name' field, this log will show it.
197- return False
198- except requests .exceptions .RequestException as e :
199- logger .error (f"Request exception creating secret '{ key_name } ': { e } " )
152+ except FireworksError as e :
153+ logger .error (f"Error creating secret '{ key_name } ': { e } " )
200154 return False
201155
202156
@@ -205,7 +159,7 @@ def get_fireworks_secret(
205159 key_name : str , # This is the identifier for the secret
206160 api_key : Optional [str ] = None ,
207161 api_base : Optional [str ] = None ,
208- ) -> Optional [Dict [ str , Any ] ]:
162+ ) -> Optional [Secret ]:
209163 """
210164 Retrieves a secret from the Fireworks AI platform by its keyName.
211165 Note: This typically does not return the secret's actual value for security reasons,
@@ -215,30 +169,25 @@ def get_fireworks_secret(
215169 resolved_api_base = api_base or get_fireworks_api_base ()
216170 resolved_account_id = account_id
217171
218- if not all ([resolved_api_key , resolved_api_base , resolved_account_id ]):
219- logger .error ("Missing Fireworks API key, base URL, or account ID for getting secret." )
220- return None
221-
222- headers = {
223- "Authorization" : f"Bearer { resolved_api_key } " ,
224- "User-Agent" : get_user_agent (),
225- }
172+ client = Fireworks (api_key = resolved_api_key , account_id = resolved_account_id , base_url = resolved_api_base )
226173 resource_id = _normalize_secret_resource_id (key_name )
227174
228175 try :
229- url = f"{ resolved_api_base } /v1/accounts/{ resolved_account_id } /secrets/{ resource_id } "
230- response = requests .get (url , headers = headers , timeout = 10 )
231- if response .status_code == 200 :
176+ secret = client .secrets .get (resource_id )
177+ if secret :
232178 logger .info (f"Successfully retrieved secret '{ key_name } '." )
233- return response .json ()
234- elif response .status_code == 404 :
235- logger .info (f"Secret '{ key_name } ' not found." )
236- return None
237- else :
238- logger .error (f"Error getting secret '{ key_name } ': { response .status_code } - { response .text } " )
239- return None
240- except requests .exceptions .RequestException as e :
241- logger .error (f"Request exception while getting secret '{ key_name } ': { e } " )
179+ return secret
180+ except NotFoundError :
181+ logger .info (f"Secret '{ key_name } ' not found." )
182+ return None
183+ except InternalServerError as e :
184+ # As per user feedback, 500 on GET might mean not found
185+ logger .warning (
186+ f"Received 500 error when getting secret '{ key_name } '. Assuming it doesn't exist. Response: { e } "
187+ )
188+ return None
189+ except FireworksError as e :
190+ logger .error (f"Error getting secret '{ key_name } ': { e } " )
242191 return None
243192
244193
@@ -259,33 +208,24 @@ def delete_fireworks_secret(
259208 logger .error ("Missing Fireworks API key, base URL, or account ID for deleting secret." )
260209 return False
261210
262- headers = {
263- "Authorization" : f"Bearer { resolved_api_key } " ,
264- "User-Agent" : get_user_agent (),
265- }
211+ client = Fireworks (api_key = resolved_api_key , account_id = resolved_account_id , base_url = resolved_api_base )
266212 resource_id = _normalize_secret_resource_id (key_name )
267213
268214 try :
269- url = f"{ resolved_api_base } /v1/accounts/{ resolved_account_id } /secrets/{ resource_id } "
270- response = requests .delete (url , headers = headers , timeout = 30 )
271- if response .status_code == 200 or response .status_code == 204 : # 204 No Content is also success for DELETE
272- logger .info (f"Successfully deleted secret '{ key_name } '." )
273- return True
274- elif response .status_code == 404 :
275- logger .info (f"Secret '{ key_name } ' not found, nothing to delete." )
276- return True
277- elif (
278- response .status_code == 500
279- ): # As per user feedback, 500 on GET might mean not found, apply same logic for DELETE
280- logger .warning (
281- f"Received 500 error when deleting secret '{ key_name } '. Assuming it might not have existed. Response: { response .text } "
282- )
283- return True # Consider deletion successful if it results in non-existence
284- else :
285- logger .error (f"Error deleting secret '{ key_name } ': { response .status_code } - { response .text } " )
286- return False
287- except requests .exceptions .RequestException as e :
288- logger .error (f"Request exception while deleting secret '{ key_name } ': { e } " )
215+ client .secrets .delete (resource_id , account_id = resolved_account_id )
216+ logger .info (f"Successfully deleted secret '{ key_name } '." )
217+ return True
218+ except NotFoundError :
219+ logger .info (f"Secret '{ key_name } ' not found, nothing to delete." )
220+ return True
221+ except InternalServerError as e :
222+ # As per user feedback, 500 on GET might mean not found, apply same logic for DELETE
223+ logger .warning (
224+ f"Received 500 error when deleting secret '{ key_name } '. Assuming it might not have existed. Response: { e } "
225+ )
226+ return True # Consider deletion successful if it results in non-existence
227+ except FireworksError as e :
228+ logger .error (f"Error deleting secret '{ key_name } ': { e } " )
289229 return False
290230
291231
@@ -319,8 +259,6 @@ def delete_fireworks_secret(
319259 logger .error (
320260 "CRITICAL: FIREWORKS_API_KEY and FIREWORKS_API_BASE must be correctly set in environment or .env file to run this test."
321261 )
322- import sys # Make sure sys is imported if using sys.exit
323-
324262 sys .exit (1 )
325263
326264 test_secret_key_name = "rewardkit-test-secret-delete-me" # Changed to be valid
@@ -331,7 +269,7 @@ def delete_fireworks_secret(
331269
332270 # 1. Ensure it doesn't exist initially (or delete if it does from a previous failed run)
333271 logger .info (f"\n [Test Step 0] Attempting to delete '{ test_secret_key_name } ' if it exists (cleanup)..." )
334- delete_fireworks_secret (test_account_id , test_secret_key_name )
272+ delete_fireworks_secret (account_id = test_account_id , key_name = test_secret_key_name )
335273 retrieved = get_fireworks_secret (test_account_id , test_secret_key_name )
336274 if retrieved is None :
337275 logger .info (f"Confirmed secret '{ test_secret_key_name } ' does not exist before creation test." )
@@ -351,8 +289,11 @@ def delete_fireworks_secret(
351289 logger .info (f"Retrieved secret metadata: { retrieved_after_create } " )
352290 # Assert against the transformed keyName that's expected in the payload/response body
353291 expected_payload_key_name = test_secret_key_name .upper ().replace ("-" , "_" )
354- assert retrieved_after_create .get ("keyName" ) == expected_payload_key_name
355- assert retrieved_after_create .get ("value" ) == test_secret_value # Also check value if returned
292+ assert retrieved_after_create .key_name == expected_payload_key_name
293+ # Note: value is typically not returned in GET responses for security reasons
294+ # The value field will be None or empty string, so we don't assert on it
295+ if retrieved_after_create .value :
296+ logger .info (f"Note: Secret value was returned (unusual): { retrieved_after_create .value [:10 ]} ..." )
356297 else :
357298 logger .error (f"Failed to retrieve secret '{ test_secret_key_name } ' after creation." )
358299
0 commit comments