Skip to content

Commit

Permalink
Update fallback to static config for running locally
Browse files Browse the repository at this point in the history
- ConfigRetrieverFactory now creates ConfigRetriever from bootstrap config
- Add runtime-config-defaults.json to serve as defaults for running locally
  • Loading branch information
BehnamMozafari committed Jan 22, 2025
1 parent 174b0c1 commit 917b0a1
Show file tree
Hide file tree
Showing 11 changed files with 98 additions and 84 deletions.
3 changes: 1 addition & 2 deletions conf/default-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,5 @@
"enclave_platform": null,
"failure_shutdown_wait_hours": 120,
"sharing_token_expiry_seconds": 2592000,
"operator_type": "public",
"config_scan_period_ms": 300000
"operator_type": "public"
}
14 changes: 13 additions & 1 deletion conf/feat-flag/feat-flag.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
{
"remote_config_feature_flag": false
"remote_config": {
"enabled": true,
"runtime_config_store": {
"type": "json",
"config": {
"identity_token_expires_after_seconds": 3600,
"refresh_token_expires_after_seconds": 86400,
"refresh_identity_token_after_seconds": 900,
"sharing_token_expiry_seconds": 2592000
},
"config_scan_period_ms": -1
}
}
}
10 changes: 9 additions & 1 deletion conf/integ-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,13 @@
"optout_api_uri": "http://localhost:8081/optout/replicate",
"salts_expired_shutdown_hours": 12,
"operator_type": "public",
"core_operator_config_path": "http://localhost:8088/operator/config"
"runtime_config_store": {
"type": "http",
"config" : {
"host": "localhost",
"port": 8088,
"path": "/operator/config"
},
"config_scan_period_ms": 300000
}
}
9 changes: 8 additions & 1 deletion conf/local-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,12 @@
"client_side_token_generate_log_invalid_http_origins": true,
"salts_expired_shutdown_hours": 12,
"operator_type": "public",
"core_operator_config_path": "http://localhost:8088/operator/config"
"runtime_config_store": {
"type": "file",
"config" : {
"path": "conf/runtime-config-defaults.json",
"format": "json"
},
"config_scan_period_ms": -1
}
}
12 changes: 10 additions & 2 deletions conf/local-e2e-docker-public-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,14 @@
"optout_status_api_enabled": true,
"cloud_refresh_interval": 30,
"salts_expired_shutdown_hours": 12,
"operator_type": "public"

"operator_type": "public",
"runtime_config_store": {
"type": "http",
"config" : {
"host": "core",
"port": 8088,
"path": "/operator/config"
},
"config_scan_period_ms": 300000
}
}
6 changes: 6 additions & 0 deletions conf/runtime-config-defaults.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"identity_token_expires_after_seconds": 3600,
"refresh_token_expires_after_seconds": 86400,
"refresh_identity_token_after_seconds": 900,
"sharing_token_expiry_seconds": 2592000
}
1 change: 0 additions & 1 deletion src/main/java/com/uid2/operator/Const.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ public class Config extends com.uid2.shared.Const.Config {
public static final String MaxInvalidPaths = "logging_limit_max_invalid_paths_per_interval";
public static final String MaxVersionBucketsPerSite = "logging_limit_max_version_buckets_per_site";

public static final String CoreConfigPath = "core_operator_config_path";
public static final String ConfigScanPeriodMs = "config_scan_period_ms";
public static final String IdentityV3 = "identity_v3";
public static final String RemoteConfigFeatureFlag = "remote_config_feature_flag";
Expand Down
38 changes: 17 additions & 21 deletions src/main/java/com/uid2/operator/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
import java.util.*;
import java.util.function.Supplier;

import static com.uid2.operator.Const.Config.ConfigScanPeriodMs;
import static io.micrometer.core.instrument.Metrics.globalRegistry;

public class Main {
Expand Down Expand Up @@ -271,36 +272,31 @@ private void run() throws Exception {
this.createVertxEventLoopsMetric();

ConfigRetrieverFactory configRetrieverFactory = new ConfigRetrieverFactory();
ConfigRetriever staticConfigRetriever = configRetrieverFactory.createJsonRetriever(vertx, config);
ConfigRetriever dynamicConfigRetriever = configRetrieverFactory.createRemoteConfigRetriever(vertx, config, this.createOperatorKeyRetriever().retrieve());
Future<ConfigService> staticConfigFuture = ConfigService.create(staticConfigRetriever);
ConfigRetriever dynamicConfigRetriever = configRetrieverFactory.create(vertx, config.getJsonObject("runtime_config_store"), this.createOperatorKeyRetriever().retrieve());
Future<ConfigService> dynamicConfigFuture = ConfigService.create(dynamicConfigRetriever);

ConfigRetriever featureFlagConfigRetriever = configRetrieverFactory.createFileRetriever(
ConfigRetriever featureFlagConfigRetriever = configRetrieverFactory.create(
vertx,
"conf/feat-flag/feat-flag.json"
new JsonObject()
.put("type", "file")
.put("config", new JsonObject()
.put("path", "conf/feat-flag/feat-flag.json")
.put("format", "json"))
.put(ConfigScanPeriodMs, 60000),
""
);
Future<JsonObject> featureFlagFuture = featureFlagConfigRetriever.getConfig();

featureFlagFuture.compose(featureFlagConfig -> {
boolean featureFlag = featureFlagConfig.getBoolean(Const.Config.RemoteConfigFeatureFlag, true);
// use static config if dynamic config fails and feature flag toggled off
return dynamicConfigFuture
.recover(throwable -> {
if (!featureFlag) {
LOGGER.warn("Dynamic config service creation failed: ", throwable);
return staticConfigFuture;
} else {
return Future.failedFuture(new Exception("Dynamic config service creation failed and feature flag is enabled: ", throwable));
}
})
.compose(dynamicConfigService -> Future.all(Future.succeededFuture(dynamicConfigService), staticConfigFuture));

featureFlagConfigRetriever.getConfig().compose(featureFlagConfig -> {
JsonObject remoteConfigJson = featureFlagConfig.getJsonObject("remote_config");
JsonObject featureFlagBootstrapConfig = remoteConfigJson.getJsonObject("runtime_config_store");
ConfigRetriever staticConfigRetriever = configRetrieverFactory.create(vertx, featureFlagBootstrapConfig, "");
return Future.all(dynamicConfigFuture, ConfigService.create(staticConfigRetriever));
})
.compose(configServiceManagerCompositeFuture -> {
ConfigService dynamicConfigService = configServiceManagerCompositeFuture.resultAt(0);
ConfigService staticConfigService = configServiceManagerCompositeFuture.resultAt(1);

boolean featureFlag = featureFlagConfigRetriever.getCachedConfig().getBoolean(Const.Config.RemoteConfigFeatureFlag, false);
boolean featureFlag = featureFlagConfigRetriever.getCachedConfig().getJsonObject("remote_config").getBoolean(Const.Config.RemoteConfigFeatureFlag, false);

ConfigServiceManager configServiceManager = new ConfigServiceManager(
vertx, dynamicConfigService, staticConfigService, featureFlag);
Expand Down
56 changes: 12 additions & 44 deletions src/main/java/com/uid2/operator/service/ConfigRetrieverFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,56 +6,24 @@
import io.vertx.core.Vertx;
import io.vertx.core.json.JsonObject;

import java.net.URI;
import java.net.URISyntaxException;

import static com.uid2.operator.Const.Config.ConfigScanPeriodMs;
import static com.uid2.operator.Const.Config.CoreConfigPath;

public class ConfigRetrieverFactory {
public ConfigRetriever createRemoteConfigRetriever(Vertx vertx, JsonObject bootstrapConfig, String operatorKey) throws URISyntaxException {
String configPath = bootstrapConfig.getString(CoreConfigPath);
URI uri = new URI(configPath);

ConfigStoreOptions httpStore = new ConfigStoreOptions()
.setType("http")
.setOptional(true)
.setConfig(new JsonObject()
.put("host", uri.getHost())
.put("port", uri.getPort())
.put("path", uri.getPath())
.put("headers", new JsonObject()
.put("Authorization", "Bearer " + operatorKey)));
public ConfigRetriever create(Vertx vertx, JsonObject bootstrapConfig, String operatorKey) {
String type = bootstrapConfig.getString("type");
JsonObject storeConfig = bootstrapConfig.getJsonObject("config");
if (type.equals("http")) {
storeConfig.put("headers", new JsonObject()
.put("Authorization", "Bearer " + operatorKey));
}

ConfigStoreOptions storeOptions = new ConfigStoreOptions()
.setType(type)
.setConfig(storeConfig);

ConfigRetrieverOptions retrieverOptions = new ConfigRetrieverOptions()
.setScanPeriod(bootstrapConfig.getLong(ConfigScanPeriodMs))
.addStore(httpStore);

return ConfigRetriever.create(vertx, retrieverOptions);
}

public ConfigRetriever createJsonRetriever(Vertx vertx, JsonObject config) {
ConfigStoreOptions jsonStore = new ConfigStoreOptions()
.setType("json")
.setConfig(config);

ConfigRetrieverOptions retrieverOptions = new ConfigRetrieverOptions()
.setScanPeriod(-1)
.addStore(jsonStore);


return ConfigRetriever.create(vertx, retrieverOptions);
}

public ConfigRetriever createFileRetriever(Vertx vertx, String path) {
ConfigStoreOptions fileStore = new ConfigStoreOptions()
.setType("file")
.setConfig(new JsonObject()
.put("path", path)
.put("format", "json"));

ConfigRetrieverOptions retrieverOptions = new ConfigRetrieverOptions()
.addStore(fileStore);
.addStore(storeOptions);

return ConfigRetriever.create(vertx, retrieverOptions);
}
Expand Down
2 changes: 0 additions & 2 deletions src/test/java/com/uid2/operator/ConfigServiceManagerTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ public class ConfigServiceManagerTest {
@BeforeEach
void setUp(Vertx vertx) {
bootstrapConfig = new JsonObject()
.put(CoreConfigPath, "/operator/config")
.put(ConfigScanPeriodMs, 300000)
.put(IDENTITY_TOKEN_EXPIRES_AFTER_SECONDS, 3600)
.put(REFRESH_TOKEN_EXPIRES_AFTER_SECONDS, 7200)
.put(REFRESH_IDENTITY_TOKEN_AFTER_SECONDS, 1800)
Expand Down
31 changes: 22 additions & 9 deletions src/test/java/com/uid2/operator/ConfigServiceTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@
import io.vertx.junit5.VertxTestContext;
import org.junit.jupiter.api.extension.ExtendWith;

import java.net.URISyntaxException;

import static com.uid2.operator.Const.Config.*;
import static com.uid2.operator.service.UIDOperatorService.*;
import static org.junit.jupiter.api.Assertions.*;
Expand All @@ -27,15 +25,22 @@
class ConfigServiceTest {
private Vertx vertx;
private JsonObject bootstrapConfig;
private JsonObject runtimeConfig;
private HttpServer server;
private ConfigRetrieverFactory configRetrieverFactory;

@BeforeEach
void setUp() {
vertx = Vertx.vertx();
bootstrapConfig = new JsonObject()
.put(CoreConfigPath, "http://localhost:8088/operator/config")
.put(ConfigScanPeriodMs, 300000)
.put("type", "http")
.put("config", new JsonObject()
.put("host", "localhost")
.put("port", 8088)
.put("path", "/operator/config"))
.put(ConfigScanPeriodMs, 300000);

runtimeConfig = new JsonObject()
.put(IDENTITY_TOKEN_EXPIRES_AFTER_SECONDS, 3600)
.put(REFRESH_TOKEN_EXPIRES_AFTER_SECONDS, 7200)
.put(REFRESH_IDENTITY_TOKEN_AFTER_SECONDS, 1800)
Expand Down Expand Up @@ -80,9 +85,9 @@ private Future<Void> startMockServer(JsonObject config) {
}

@Test
void testGetConfig(VertxTestContext testContext) throws URISyntaxException {
ConfigRetriever configRetriever = configRetrieverFactory.createRemoteConfigRetriever(vertx, bootstrapConfig, "");
JsonObject httpStoreConfig = bootstrapConfig;
void testGetConfig(VertxTestContext testContext) {
ConfigRetriever configRetriever = configRetrieverFactory.create(vertx, bootstrapConfig, "");
JsonObject httpStoreConfig = runtimeConfig;
startMockServer(httpStoreConfig)
.compose(v -> ConfigService.create(configRetriever))
.compose(configService -> {
Expand All @@ -100,7 +105,11 @@ void testInvalidConfigRevertsToPrevious(VertxTestContext testContext) {
JsonObject invalidConfig = new JsonObject()
.put(IDENTITY_TOKEN_EXPIRES_AFTER_SECONDS, 1000)
.put(REFRESH_TOKEN_EXPIRES_AFTER_SECONDS, 2000);
ConfigRetriever spyRetriever = spy(configRetrieverFactory.createJsonRetriever(vertx, invalidConfig));
JsonObject jsonBootstrapConfig = new JsonObject()
.put("type", "json")
.put("config", invalidConfig)
.put(ConfigScanPeriodMs, -1);
ConfigRetriever spyRetriever = spy(configRetrieverFactory.create(vertx, jsonBootstrapConfig, ""));
when(spyRetriever.getCachedConfig()).thenReturn(lastConfig);
ConfigService.create(spyRetriever)
.compose(configService -> {
Expand All @@ -116,7 +125,11 @@ void testFirstInvalidConfigThrowsRuntimeException(VertxTestContext testContext)
JsonObject invalidConfig = new JsonObject()
.put(IDENTITY_TOKEN_EXPIRES_AFTER_SECONDS, 1000)
.put(REFRESH_TOKEN_EXPIRES_AFTER_SECONDS, 2000);
ConfigRetriever configRetriever = configRetrieverFactory.createJsonRetriever(vertx, invalidConfig);
JsonObject jsonBootstrapConfig = new JsonObject()
.put("type", "json")
.put("config", invalidConfig)
.put(ConfigScanPeriodMs, -1);
ConfigRetriever configRetriever = configRetrieverFactory.create(vertx, jsonBootstrapConfig, "");
ConfigService.create(configRetriever)
.onComplete(testContext.failing(throwable -> {
assertThrows(RuntimeException.class, () -> {
Expand Down

0 comments on commit 917b0a1

Please sign in to comment.