@@ -131,7 +131,6 @@ public class AIAPITestCase extends APIMIntegrationBaseTest {
131
131
private final String defaultProductionEndpointId = "default_production_endpoint" ;
132
132
private final String defaultProductionEndpointName = "Default Production Endpoint" ;
133
133
private final String newVersion = "2.0.0" ;
134
- private final String newVersionContext = mistralAPIContext + "-v2" ;
135
134
private final String failoverEndpointUrl = "/failover-endpoint" ;
136
135
private final String failoverEndpointName = "Failover Endpoint" ;
137
136
private String productionEndpointId ;
@@ -816,7 +815,7 @@ public void testAIApiInvocationAfterAddingApiLevelModelRoundRobinPolicy() throws
816
815
public void testCreateNewVersionWithFailoverPolicy () throws Exception {
817
816
// Create new version of the API
818
817
HttpResponse copyApiResponse = restAPIPublisher .copyAPI (newVersion , mistralAPIId , false );
819
- Assert .assertEquals (copyApiResponse .getResponseCode (), HttpStatus .SC_CREATED ,
818
+ Assert .assertEquals (copyApiResponse .getResponseCode (), HttpStatus .SC_OK ,
820
819
"Failed to create new version of API" );
821
820
822
821
newVersionApiId = copyApiResponse .getData ();
@@ -829,38 +828,64 @@ public void testCreateNewVersionWithFailoverPolicy() throws Exception {
829
828
830
829
APIDTO newVersionApiDto = new Gson ().fromJson (getNewVersionApiResponse .getData (), APIDTO .class );
831
830
Assert .assertEquals (newVersionApiDto .getVersion (), newVersion , "API version should match" );
831
+
832
+ // Add a new endpoint with failover URL for the new version
833
+ String failoverEndpointConfig = readFile (resourcePath + "prod-endpoint-add-endpoint-config.json" );
834
+ JSONObject failoverEndpointConfigObj = new JSONObject (failoverEndpointConfig );
835
+ JSONObject productionEndpoints = new JSONObject ();
836
+ productionEndpoints .put ("url" , endpointHost + ":" + endpointPort + failoverEndpointUrl );
837
+ failoverEndpointConfigObj .put ("production_endpoints" , productionEndpoints );
838
+
839
+ Map <String , Object > failoverEndpointConfigMap = new Gson ().fromJson (failoverEndpointConfigObj .toString (), Map .class );
840
+ HttpResponse addFailoverEndpointResponse = restAPIPublisher .addApiEndpoint (newVersionApiId , failoverEndpointName ,
841
+ productionDeploymentStage , failoverEndpointConfigMap );
842
+ Assert .assertEquals (addFailoverEndpointResponse .getResponseCode (), HttpStatus .SC_CREATED ,
843
+ "Failed to add failover endpoint to new version API" );
832
844
845
+ // Extract failover endpoint ID from response
846
+ JSONObject failoverEndpointResponse = new JSONObject (addFailoverEndpointResponse .getData ());
847
+ failoverEndpointId = failoverEndpointResponse .getString ("id" );
848
+ Assert .assertNotNull (failoverEndpointId , "Failover endpoint ID should not be null" );
849
+
850
+ // Update the API to set the new endpoint as primary production endpoint
851
+ newVersionApiDto .setPrimaryProductionEndpointId (failoverEndpointId );
852
+
833
853
// Remove the round-robin policy and add failover policy
834
854
String failoverPolicyName = "modelFailover" ;
835
855
Assert .assertNotNull (policyMap .get (failoverPolicyName ), "Unable to find a common policy with name " + failoverPolicyName );
836
-
856
+
837
857
Map <String , Object > failoverAttributeMap = new HashMap <>();
838
858
JSONObject failoverConfigs = new JSONObject ();
839
-
859
+
840
860
// Configure production failover
841
861
JSONObject productionConfig = new JSONObject ();
842
862
JSONObject targetModel = new JSONObject ();
843
863
targetModel .put ("model" , model1 );
844
864
targetModel .put ("endpointId" , failoverEndpointId );
845
865
targetModel .put ("endpointName" , failoverEndpointName );
846
866
productionConfig .put ("targetModel" , targetModel );
847
-
867
+
848
868
List <JSONObject > fallbackModels = new ArrayList <>();
849
869
JSONObject fallbackModel = new JSONObject ();
850
870
fallbackModel .put ("model" , model3 );
851
- fallbackModel .put ("endpointId" , productionEndpointId );
852
- fallbackModel .put ("endpointName" , productionEndpointName );
871
+ fallbackModel .put ("endpointId" , defaultProductionEndpointId );
872
+ fallbackModel .put ("endpointName" , defaultProductionEndpointName );
853
873
fallbackModels .add (fallbackModel );
854
874
productionConfig .put ("fallbackModels" , fallbackModels );
855
-
875
+
876
+ // Configure sandbox failover (empty in this case)
877
+ JSONObject sandboxConfig = new JSONObject ();
878
+ sandboxConfig .put ("targetModel" , new JSONObject ());
879
+ sandboxConfig .put ("fallbackModels" , new ArrayList <JSONObject >());
880
+
856
881
failoverConfigs .put ("production" , productionConfig );
857
- failoverConfigs .put ("sandbox" , new JSONObject () );
858
- failoverConfigs .put ("requestTimeout" , "10 " );
882
+ failoverConfigs .put ("sandbox" , sandboxConfig );
883
+ failoverConfigs .put ("requestTimeout" , "60 " );
859
884
failoverConfigs .put ("suspendDuration" , "5" );
860
885
861
886
String configString = failoverConfigs .toString ().replace ("\" " , "'" );
862
887
failoverAttributeMap .put ("failoverConfigs" , configString );
863
-
888
+
864
889
// Create failover policy
865
890
List <OperationPolicyDTO > requestPolicyList = new ArrayList <>();
866
891
OperationPolicyDTO failoverPolicyDTO = new OperationPolicyDTO ();
@@ -869,41 +894,20 @@ public void testCreateNewVersionWithFailoverPolicy() throws Exception {
869
894
failoverPolicyDTO .setPolicyId (policyMap .get (failoverPolicyName ));
870
895
failoverPolicyDTO .setParameters (failoverAttributeMap );
871
896
requestPolicyList .add (failoverPolicyDTO );
872
-
897
+
873
898
APIOperationPoliciesDTO apiOperationPoliciesDTO = new APIOperationPoliciesDTO ();
874
899
apiOperationPoliciesDTO .setRequest (requestPolicyList );
875
900
newVersionApiDto .setApiPolicies (apiOperationPoliciesDTO );
876
-
901
+
877
902
// Update the new version API with failover policy
878
903
HttpResponse updateResponse = restAPIPublisher .updateAPIWithHttpInfo (newVersionApiDto );
879
904
Assert .assertEquals (updateResponse .getResponseCode (), HttpStatus .SC_OK ,
880
- "Failed to update new version API with failover policy" );
881
-
882
- // Add a new endpoint with failover URL for the new version
883
- String failoverEndpointConfig = readFile (resourcePath + "prod-endpoint-add-endpoint-config.json" );
884
- JSONObject failoverEndpointConfigObj = new JSONObject (failoverEndpointConfig );
885
- JSONObject productionEndpoints = new JSONObject ();
886
- productionEndpoints .put ("url" , endpointHost + ":" + endpointPort + failoverEndpointUrl );
887
- failoverEndpointConfigObj .put ("production_endpoints" , productionEndpoints );
888
-
889
- Map <String , Object > failoverEndpointConfigMap = new Gson ().fromJson (failoverEndpointConfigObj .toString (), Map .class );
890
- HttpResponse addFailoverEndpointResponse = restAPIPublisher .addApiEndpoint (newVersionApiId , failoverEndpointName ,
891
- productionDeploymentStage , failoverEndpointConfigMap );
892
- Assert .assertEquals (addFailoverEndpointResponse .getResponseCode (), HttpStatus .SC_CREATED ,
893
- "Failed to add failover endpoint to new version API" );
894
-
895
- // Extract failover endpoint ID from response
896
- JSONObject failoverEndpointResponse = new JSONObject (addFailoverEndpointResponse .getData ());
897
- failoverEndpointId = failoverEndpointResponse .getString ("id" );
898
- Assert .assertNotNull (failoverEndpointId , "Failover endpoint ID should not be null" );
899
-
900
- // Update the API to set the new endpoint as primary production endpoint
901
- newVersionApiDto .setPrimaryProductionEndpointId (failoverEndpointId );
905
+ "Failed to update new version API with failover policy and updated primary production endpoint" );
902
906
903
907
// Create revision and deploy the new version
904
908
String revisionUUID = createAPIRevisionAndDeployUsingRest (newVersionApiId , restAPIPublisher );
905
909
Assert .assertNotNull (revisionUUID , "Failed to create and deploy revision for new version API" );
906
-
910
+
907
911
// Publish the new version API
908
912
HttpResponse lifecycleResponse = restAPIPublisher .changeAPILifeCycleStatusToPublish (newVersionApiId , false );
909
913
Assert .assertEquals (lifecycleResponse .getResponseCode (), HttpStatus .SC_OK ,
@@ -914,16 +918,16 @@ public void testCreateNewVersionWithFailoverPolicy() throws Exception {
914
918
newVersionApiDto .getVersion (), APIMIntegrationConstants .IS_API_EXISTS );
915
919
916
920
// Subscribe to the new version API
917
- SubscriptionDTO subscriptionDTO = restAPIStore .subscribeToAPI (newVersionApiId , applicationId ,
918
- APIMIntegrationConstants .API_TIER .UNLIMITED );
919
- Assert .assertNotNull (subscriptionDTO , "New version API subscription failed" );
921
+ // SubscriptionDTO subscriptionDTO = restAPIStore.subscribeToAPI(newVersionApiId, applicationId,
922
+ // APIMIntegrationConstants.API_TIER.UNLIMITED);
923
+ // Assert.assertNotNull(subscriptionDTO, "New version API subscription failed");
920
924
921
925
// Invoke the new version API to test failover
922
926
Map <String , String > requestHeaders = new HashMap <>();
923
927
requestHeaders .put ("ApiKey" , apiKey );
924
- String invokeURL = getAPIInvocationURLHttp (newVersionContext , newVersion ) + mistralAPIResource ;
928
+ String invokeURL = getAPIInvocationURLHttp (mistralAPIContext , newVersion ) + mistralAPIResource ;
925
929
HttpResponse serviceResponse = HTTPSClientUtils .doPost (invokeURL , requestHeaders , mistralPayload );
926
-
930
+
927
931
// Verify that the API call succeeded (failover should have worked)
928
932
Assert .assertEquals (serviceResponse .getResponseCode (), HttpStatus .SC_OK ,
929
933
"API invocation should succeed due to failover" );
@@ -1053,24 +1057,24 @@ private void startWiremockServer() {
1053
1057
.withHeader ("Content-Type" , "application/json" )
1054
1058
.withBody (model1Response )));
1055
1059
1056
- // Stub for secured AI API (with Authorization header value of Bearer 456)
1060
+ // Stub for round-robin policy: model1 request routed to model2 (80% weight)
1061
+ // Using more flexible matching with containsString to handle potential JSON formatting issues
1057
1062
wireMockServer .stubFor (WireMock .post (urlEqualTo (mistralAPIEndpoint2 + mistralAPIResource ))
1058
1063
.withHeader ("Authorization" , WireMock .matching ("Bearer 456" ))
1059
- // .withRequestBody(equalTo(model1))
1060
- .withRequestBody (matchingJsonPath ("$.model" , equalTo (model1 )))
1064
+ .withRequestBody (WireMock .containing (model2 ))
1061
1065
.willReturn (aResponse ()
1062
1066
.withStatus (200 )
1063
1067
.withHeader ("Content-Type" , "application/json" )
1064
- .withBody (model1Response )));
1068
+ .withBody (model2Response )));
1065
1069
1066
- // Stub for model2 (mistral-medium-latest)
1070
+ // Stub for round-robin policy: model1 request routed to model3 (20% weight)
1067
1071
wireMockServer .stubFor (WireMock .post (urlEqualTo (mistralAPIEndpoint2 + mistralAPIResource ))
1068
1072
.withHeader ("Authorization" , WireMock .matching ("Bearer 456" ))
1069
- .withRequestBody (matchingJsonPath ( "$.model" , equalTo ( model2 ) ))
1073
+ .withRequestBody (WireMock . containing ( model3 ))
1070
1074
.willReturn (aResponse ()
1071
1075
.withStatus (200 )
1072
1076
.withHeader ("Content-Type" , "application/json" )
1073
- .withBody (model2Response )));
1077
+ .withBody (model3Response )));
1074
1078
1075
1079
// Stub for model3 (mistral-large-latest)
1076
1080
// wireMockServer.stubFor(WireMock.post(urlEqualTo(mistralAPIEndpoint2 + mistralAPIResource))
@@ -1095,9 +1099,18 @@ private void startWiremockServer() {
1095
1099
// .withTransformers("response-template")));
1096
1100
1097
1101
// Stub for /mistral endpoint with Bearer 123 and model3
1102
+ // Using flexible matching to handle JSON formatting issues
1098
1103
wireMockServer .stubFor (WireMock .post (urlEqualTo (mistralAPIEndpoint + mistralAPIResource ))
1099
1104
.withHeader ("Authorization" , WireMock .matching ("Bearer 123" ))
1100
- .withRequestBody (matchingJsonPath ("$.model" , equalTo (model3 )))
1105
+ .withRequestBody (WireMock .containing (model3 ))
1106
+ .willReturn (aResponse ()
1107
+ .withStatus (200 )
1108
+ .withHeader ("Content-Type" , "application/json" )
1109
+ .withBody (model3Response )));
1110
+
1111
+ wireMockServer .stubFor (WireMock .post (urlEqualTo (mistralAPIEndpoint + '/' + newVersion + mistralAPIResource ))
1112
+ .withHeader ("Authorization" , WireMock .matching ("Bearer 123" ))
1113
+ .withRequestBody (WireMock .containing (model3 ))
1101
1114
.willReturn (aResponse ()
1102
1115
.withStatus (200 )
1103
1116
.withHeader ("Content-Type" , "application/json" )
@@ -1106,7 +1119,7 @@ private void startWiremockServer() {
1106
1119
// Stub for failover endpoint that returns 500 (to trigger failover)
1107
1120
wireMockServer .stubFor (WireMock .post (urlEqualTo (failoverEndpointUrl + mistralAPIResource ))
1108
1121
.withHeader ("Authorization" , WireMock .matching ("Bearer 123" ))
1109
- .withRequestBody (matchingJsonPath ( "$.model" , equalTo (model1 ) ))
1122
+ .withRequestBody (WireMock . containing (model1 ))
1110
1123
.willReturn (aResponse ()
1111
1124
.withStatus (500 )
1112
1125
.withHeader ("Content-Type" , "application/json" )
0 commit comments