5151
5252@ ExtendWith (MockitoExtension .class )
5353class AgentlessConfigurationSourceTest {
54- private static final String CONFIG_PATH = "/api/v2/feature-flagging/config/server-distribution " ;
54+ private static final String CONFIG_PATH = "/api/v2/feature-flagging/config/rules-based/server " ;
5555
5656 @ Mock private FeatureFlaggingGateway .ConfigListener listener ;
5757
@@ -62,33 +62,33 @@ void cleanup() {
6262 }
6363
6464 @ Test
65- void derivesDatadogApiServerDistributionEndpointFromSiteAndEnv () {
65+ void derivesDatadogUfcCdnEndpointFromSiteAndEnv () {
6666 final Config config = config ("datad0g.com" , "staging env" );
6767
6868 assertEquals (
69- "https://api. datad0g.com/api/v2/feature-flagging/config/server-distribution ?dd_env=staging%20env" ,
69+ "https://ufc-server.ff-cdn. datad0g.com/api/v2/feature-flagging/config/rules-based/server ?dd_env=staging%20env" ,
7070 AgentlessConfigurationSource .endpoint (config ).toString ());
7171 }
7272
7373 @ Test
74- void derivesDatadogApiServerDistributionEndpointWithoutEnv () {
74+ void derivesDatadogUfcCdnEndpointWithoutEnv () {
7575 assertEquals (
76- "https://api. datadoghq.com/api/v2/feature-flagging/config/server-distribution " ,
76+ "https://ufc-server.ff-cdn. datadoghq.com/api/v2/feature-flagging/config/rules-based/server " ,
7777 AgentlessConfigurationSource .endpoint (config ("datadoghq.com" , "" )).toString ());
7878 assertEquals (
79- "https://api. datadoghq.com/api/v2/feature-flagging/config/server-distribution " ,
79+ "https://ufc-server.ff-cdn. datadoghq.com/api/v2/feature-flagging/config/rules-based/server " ,
8080 AgentlessConfigurationSource .endpoint (config ("datadoghq.com" , null )).toString ());
8181 }
8282
8383 @ Test
84- void appendsServerDistributionPathToConfiguredAgentlessBaseUrl () {
84+ void appendsRulesBasedServerPathToConfiguredAgentlessBaseUrl () {
8585 final Config config = config ();
8686 lenient ()
8787 .when (config .getFeatureFlaggingConfigurationSourceAgentlessBaseUrl ())
8888 .thenReturn ("http://mock-backend:8080" );
8989
9090 assertEquals (
91- "http://mock-backend:8080/api/v2/feature-flagging/config/server-distribution " ,
91+ "http://mock-backend:8080/api/v2/feature-flagging/config/rules-based/server " ,
9292 AgentlessConfigurationSource .endpoint (config ).toString ());
9393 }
9494
@@ -116,7 +116,7 @@ void rejectsInvalidConfiguredAgentlessBaseUrl() {
116116 }
117117
118118 @ Test
119- void rejectsInvalidDatadogApiServerDistributionEndpoint () {
119+ void rejectsInvalidDatadogUfcCdnEndpoint () {
120120 assertThrows (
121121 IllegalArgumentException .class ,
122122 () -> AgentlessConfigurationSource .endpoint (config ("datadoghq.com:bad" , "" )));
@@ -359,18 +359,43 @@ void realHttpClientTimesOutDelayedResponse() throws Exception {
359359 }
360360
361361 @ Test
362- void appliesAcceptedUfcThroughGatewayAndSendsApiKey () throws Exception {
362+ void appliesAcceptedJsonApiUfcThroughGatewayAndSendsApiKey () throws Exception {
363363 final FakeClient client = new FakeClient (response (200 , "etag-a" , emptyConfig ()));
364364 final AgentlessConfigurationSource service = service (client );
365+ final ArgumentCaptor <ServerConfiguration > configuration =
366+ ArgumentCaptor .forClass (ServerConfiguration .class );
365367 FeatureFlaggingGateway .addConfigListener (listener );
366368
367369 assertTrue (service .pollOnce ());
368370
369- verify (listener ).accept (any (ServerConfiguration .class ));
371+ verify (listener ).accept (configuration .capture ());
372+ assertEquals ("2026-07-15T19:57:07.219869778Z" , configuration .getValue ().createdAt );
373+ assertNull (configuration .getValue ().format );
374+ assertEquals ("Staging" , configuration .getValue ().environment .name );
375+ assertTrue (configuration .getValue ().flags .isEmpty ());
370376 assertEquals ("test-api-key" , client .requests .get (0 ).apiKey );
371377 assertNull (client .requests .get (0 ).etag );
372378 }
373379
380+ @ Test
381+ void appliesRawUfcFromConfiguredCompatibilityEndpoint () throws Exception {
382+ final FakeClient client = new FakeClient (response (200 , "etag-a" , emptyConfigAttributes ()));
383+ final Config config = config ();
384+ lenient ()
385+ .when (config .getFeatureFlaggingConfigurationSourceAgentlessBaseUrl ())
386+ .thenReturn ("http://compatibility-backend/custom/ufc" );
387+ final AgentlessConfigurationSource service = service (client , config );
388+ final ArgumentCaptor <ServerConfiguration > configuration =
389+ ArgumentCaptor .forClass (ServerConfiguration .class );
390+ FeatureFlaggingGateway .addConfigListener (listener );
391+
392+ assertTrue (service .pollOnce ());
393+
394+ verify (listener ).accept (configuration .capture ());
395+ assertEquals ("Staging" , configuration .getValue ().environment .name );
396+ assertTrue (configuration .getValue ().flags .isEmpty ());
397+ }
398+
374399 @ Test
375400 void ignoresBlankEtag () throws Exception {
376401 final FakeClient client =
@@ -486,10 +511,19 @@ void rejectsForbiddenNonOkMissingBodyAndNullConfiguration() throws Exception {
486511 response (404 , null , null ),
487512 response (600 , null , null ),
488513 response (200 , null , null ),
489- response (200 , null , "null" ));
514+ response (200 , null , "null" ),
515+ response (200 , null , jsonApiResponse ("other-configuration" , emptyConfigAttributes ())),
516+ response (200 , null , "{\" data\" :null}" ),
517+ response (
518+ 200 , null , "{\" data\" :{\" id\" :\" 1\" ,\" type\" :\" universal-flag-configuration\" }}" ),
519+ response (200 , null , emptyConfigAttributes ()));
490520 final AgentlessConfigurationSource service = service (client );
491521 FeatureFlaggingGateway .addConfigListener (listener );
492522
523+ assertFalse (service .pollOnce ());
524+ assertFalse (service .pollOnce ());
525+ assertFalse (service .pollOnce ());
526+ assertFalse (service .pollOnce ());
493527 assertFalse (service .pollOnce ());
494528 assertFalse (service .pollOnce ());
495529 assertFalse (service .pollOnce ());
@@ -902,6 +936,16 @@ private static AgentlessConfigurationSource service(final FakeClient client) {
902936 return service (client , delay -> {}, () -> 1.0 );
903937 }
904938
939+ private static AgentlessConfigurationSource service (
940+ final FakeClient client , final Config config ) {
941+ return new AgentlessConfigurationSource (
942+ HttpUrl .get ("http://localhost" + CONFIG_PATH ),
943+ config ,
944+ 30_000 ,
945+ client ,
946+ Executors .newSingleThreadScheduledExecutor ());
947+ }
948+
905949 private static AgentlessConfigurationSource service (
906950 final FakeClient client ,
907951 final AgentlessConfigurationSource .RetrySleeper retrySleeper ,
@@ -943,19 +987,32 @@ private static AgentlessConfigurationSource.UfcHttpResponse response(
943987 }
944988
945989 private static String emptyConfig () {
990+ return jsonApiResponse ("universal-flag-configuration" , emptyConfigAttributes ());
991+ }
992+
993+ private static String emptyConfigAttributes () {
946994 return "{"
947- + "\" createdAt\" :\" 2024-04-17T19:40:53.716Z\" ,"
948- + "\" format\" :\" SERVER\" ,"
949- + "\" environment\" :{\" name\" :\" Test\" },"
995+ + "\" createdAt\" :\" 2026-07-15T19:57:07.219869778Z\" ,"
996+ + "\" environment\" :{\" name\" :\" Staging\" },"
950997 + "\" flags\" :{}"
951998 + "}" ;
952999 }
9531000
1001+ private static String jsonApiResponse (final String type , final String attributes ) {
1002+ return "{\" data\" :{"
1003+ + "\" id\" :\" 1\" ,"
1004+ + "\" type\" :\" "
1005+ + type
1006+ + "\" ,"
1007+ + "\" attributes\" :"
1008+ + attributes
1009+ + "}}" ;
1010+ }
1011+
9541012 private static String largeConfig (final int flagCount ) {
9551013 final StringBuilder json =
9561014 new StringBuilder (
957- "{\" createdAt\" :\" 2024-04-17T19:40:53.716Z\" ,"
958- + "\" format\" :\" SERVER\" ,"
1015+ "{\" createdAt\" :\" 2026-07-15T19:57:07.219869778Z\" ,"
9591016 + "\" environment\" :{\" name\" :\" Large Test\" },"
9601017 + "\" flags\" :{" );
9611018 for (int index = 0 ; index < flagCount ; index ++) {
@@ -972,7 +1029,7 @@ private static String largeConfig(final int flagCount) {
9721029 + "\" variations\" :{\" on\" :{\" key\" :\" on\" ,\" value\" :\" on\" }},"
9731030 + "\" allocations\" :[]}" );
9741031 }
975- return json .append ("}}" ).toString ();
1032+ return jsonApiResponse ( "universal-flag-configuration" , json .append ("}}" ).toString () );
9761033 }
9771034
9781035 private static void awaitCalls (final FakeClient client , final int count ) throws Exception {
0 commit comments