feat: support enable/disable cloud location provider via configuration. (#1799)

Signed-off-by: Haotian Zhang <928016560@qq.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2024
Haotian Zhang 5 days ago committed by GitHub
parent 0b9d8cdadd
commit 0f2d7073a4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -5,3 +5,4 @@
- [feat: Update config server IP to 127.0.0.1 and adjust tests.](https://github.com/Tencent/spring-cloud-tencent/pull/1796)
- [feat: Support Polaris config env value and add related tests](https://github.com/Tencent/spring-cloud-tencent/pull/1797)
- [refactor: modify the initialization of ApplicationContextAwareUtils.](https://github.com/Tencent/spring-cloud-tencent/pull/1798)
- [feat: support enable/disable cloud location provider via configuration.](https://github.com/Tencent/spring-cloud-tencent/pull/1799)

@ -229,5 +229,10 @@ public class OrderConstant {
* Order of fault injection modifier.
*/
public static Integer FAULT_INJECTION_ORDER = 2;
/**
* Order of location configuration modifier.
*/
public static Integer LOCATION_ORDER = 2;
}
}

@ -36,15 +36,17 @@ public class PostInitPolarisSDKContext {
String zone = staticMetadataManager.getZone();
String campus = staticMetadataManager.getCampus();
ValueContext valueContext = sdkContext.getValueContext();
if (StringUtils.isNotBlank(region)) {
valueContext.setValue(RoutingProto.NearbyRoutingConfig.LocationLevel.REGION.name(), region);
}
if (zone != null) {
valueContext.setValue(RoutingProto.NearbyRoutingConfig.LocationLevel.ZONE.name(), zone);
}
if (StringUtils.isNotBlank(campus)) {
valueContext.setValue(RoutingProto.NearbyRoutingConfig.LocationLevel.CAMPUS.name(), campus);
if (!StringUtils.isAllEmpty(region, zone, campus)) {
ValueContext valueContext = sdkContext.getValueContext();
if (StringUtils.isNotBlank(region)) {
valueContext.setValue(RoutingProto.NearbyRoutingConfig.LocationLevel.REGION.name(), region);
}
if (zone != null) {
valueContext.setValue(RoutingProto.NearbyRoutingConfig.LocationLevel.ZONE.name(), zone);
}
if (StringUtils.isNotBlank(campus)) {
valueContext.setValue(RoutingProto.NearbyRoutingConfig.LocationLevel.CAMPUS.name(), campus);
}
}
}
}

@ -30,6 +30,8 @@ import com.tencent.cloud.polaris.context.config.extend.consul.ConsulProperties;
import com.tencent.cloud.polaris.context.config.extend.tsf.TsfCoreProperties;
import com.tencent.cloud.polaris.context.config.extend.tsf.TsfInstanceMetadataProvider;
import com.tencent.cloud.polaris.context.config.extend.tsf.TsfTlsProperties;
import com.tencent.cloud.polaris.context.config.location.PolarisLocationConfigModifier;
import com.tencent.cloud.polaris.context.config.location.PolarisLocationProperties;
import com.tencent.cloud.polaris.context.event.PushGatewayEventReporterConfigModifier;
import com.tencent.cloud.polaris.context.event.PushGatewayEventReporterProperties;
import com.tencent.cloud.polaris.context.listener.PolarisContextApplicationEventListener;
@ -121,4 +123,16 @@ public class PolarisContextAutoConfiguration {
public TsfInstanceMetadataProvider tsfInstanceMetadataProvider(TsfCoreProperties tsfCoreProperties) {
return new TsfInstanceMetadataProvider(tsfCoreProperties);
}
@Bean
@ConditionalOnMissingBean
public PolarisLocationProperties polarisLocationProperties() {
return new PolarisLocationProperties();
}
@Bean
@ConditionalOnMissingBean
public PolarisLocationConfigModifier polarisLocationConfigModifier(PolarisLocationProperties polarisLocationProperties) {
return new PolarisLocationConfigModifier(polarisLocationProperties);
}
}

@ -159,6 +159,9 @@ public final class TsfCoreEnvironmentPostProcessor implements EnvironmentPostPro
if (TsfContextUtils.isOnlyTsfConsulEnabled(environment)) {
// context
defaultProperties.put("spring.cloud.polaris.location.cloud.enabled", environment.getProperty("spring.cloud.polaris.location.cloud.enabled", "false"));
// discovery
defaultProperties.put("spring.cloud.polaris.discovery.enabled", "false");
defaultProperties.put("spring.cloud.polaris.discovery.register", "false");

@ -0,0 +1,72 @@
/*
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
*
* Copyright (C) 2021 Tencent. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.tencent.cloud.polaris.context.config.location;
import java.util.List;
import com.tencent.cloud.common.constant.OrderConstant;
import com.tencent.cloud.polaris.context.PolarisConfigModifier;
import com.tencent.polaris.api.plugin.location.LocationProvider;
import com.tencent.polaris.factory.config.ConfigurationImpl;
import com.tencent.polaris.factory.config.global.LocationConfigImpl;
import com.tencent.polaris.factory.config.global.LocationProviderConfigImpl;
/**
* Config modifier for Polaris location providers.
*
* @author Haotian Zhang
*/
public class PolarisLocationConfigModifier implements PolarisConfigModifier {
private final PolarisLocationProperties properties;
public PolarisLocationConfigModifier(PolarisLocationProperties properties) {
this.properties = properties;
}
@Override
public void modify(ConfigurationImpl configuration) {
LocationConfigImpl locationConfig = (LocationConfigImpl) configuration.getGlobal().getLocation();
List<LocationProviderConfigImpl> providers = locationConfig.getProviders();
if (providers == null) {
return;
}
String cloudTypeName = LocationProvider.ProviderType.CLOUD.getName();
if (!properties.getCloud().isEnabled()) {
// Remove cloud provider if disabled
providers.removeIf(p -> cloudTypeName.equals(p.getType()));
return;
}
// Only add the cloud provider entry if it does not already exist
boolean cloudProviderExists = providers.stream()
.anyMatch(p -> cloudTypeName.equals(p.getType()));
if (!cloudProviderExists) {
LocationProviderConfigImpl cloudProviderConfig = new LocationProviderConfigImpl();
cloudProviderConfig.setType(cloudTypeName);
providers.add(cloudProviderConfig);
}
}
@Override
public int getOrder() {
return OrderConstant.Modifier.LOCATION_ORDER;
}
}

@ -0,0 +1,75 @@
/*
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
*
* Copyright (C) 2021 Tencent. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.tencent.cloud.polaris.context.config.location;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* Properties for Polaris location provider configuration.
*
* @author Haotian Zhang
*/
@ConfigurationProperties(prefix = "spring.cloud.polaris.location")
public class PolarisLocationProperties {
/**
* Cloud location provider configuration.
*/
private Cloud cloud = new Cloud();
public Cloud getCloud() {
return cloud;
}
public void setCloud(Cloud cloud) {
this.cloud = cloud;
}
@Override
public String toString() {
return "PolarisLocationProperties{" +
"cloud=" + cloud +
'}';
}
/**
* Properties for cloud location provider.
*/
public static class Cloud {
/**
* Whether to enable the cloud location provider. Default is true.
*/
private boolean enabled = true;
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
@Override
public String toString() {
return "Cloud{" +
"enabled=" + enabled +
'}';
}
}
}

@ -0,0 +1,133 @@
/*
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
*
* Copyright (C) 2021 Tencent. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.tencent.cloud.polaris.context.config.location;
import com.tencent.cloud.common.constant.OrderConstant;
import com.tencent.cloud.polaris.context.PolarisSDKContextManager;
import com.tencent.polaris.api.plugin.location.LocationProvider;
import com.tencent.polaris.factory.config.global.LocationConfigImpl;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Test for {@link PolarisLocationConfigModifier}.
*
* @author Haotian Zhang
*/
@DisplayName("PolarisLocationConfigModifier")
class PolarisLocationConfigModifierTest {
private final ApplicationContextRunner enabledContextRunner = new ApplicationContextRunner()
.withUserConfiguration(TestApplication.class)
.withPropertyValues("spring.cloud.polaris.enabled=true")
.withPropertyValues("spring.cloud.polaris.location.cloud.enabled=true")
.withPropertyValues("spring.application.name=test")
.withPropertyValues("spring.cloud.gateway.enabled=false");
private final ApplicationContextRunner disabledContextRunner = new ApplicationContextRunner()
.withUserConfiguration(TestApplication.class)
.withPropertyValues("spring.cloud.polaris.enabled=true")
.withPropertyValues("spring.cloud.polaris.location.cloud.enabled=false")
.withPropertyValues("spring.application.name=test")
.withPropertyValues("spring.cloud.gateway.enabled=false");
@BeforeEach
void setUp() {
PolarisSDKContextManager.innerDestroy();
}
/**
* Test purpose: verify that cloud location provider is added by default.
* Test scenario: no explicit location config, cloud.enabled defaults to true.
* Verification: providers list contains one entry with type "cloud".
*/
@DisplayName("cloud provider is added when enabled by default")
@Test
void testModify_cloudEnabledByDefault() {
enabledContextRunner.run(context -> {
PolarisSDKContextManager manager = context.getBean(PolarisSDKContextManager.class);
LocationConfigImpl locationConfig = (LocationConfigImpl) manager.getSDKContext()
.getConfig().getGlobal().getLocation();
boolean hasCloudProvider = locationConfig.getProviders().stream()
.anyMatch(p -> LocationProvider.ProviderType.CLOUD.getName().equals(p.getType()));
assertThat(hasCloudProvider).isTrue();
});
}
/**
* Test purpose: verify that cloud location provider is removed when disabled.
* Test scenario: spring.cloud.polaris.location.cloud.enabled=false.
* Verification: providers list contains no entry with type "cloud".
*/
@DisplayName("cloud provider is removed when disabled")
@Test
void testModify_cloudDisabled() {
disabledContextRunner.run(context -> {
PolarisSDKContextManager manager = context.getBean(PolarisSDKContextManager.class);
LocationConfigImpl locationConfig = (LocationConfigImpl) manager.getSDKContext()
.getConfig().getGlobal().getLocation();
boolean hasCloudProvider = locationConfig.getProviders().stream()
.anyMatch(p -> LocationProvider.ProviderType.CLOUD.getName().equals(p.getType()));
assertThat(hasCloudProvider).isFalse();
});
}
/**
* Test purpose: verify that no duplicate cloud provider entry is added.
* Test scenario: cloud is enabled (default), Spring context is loaded once.
* Verification: providers list contains exactly one entry with type "cloud".
*/
@DisplayName("no duplicate cloud provider entry is added")
@Test
void testModify_noDuplicateCloudProvider() {
enabledContextRunner.run(context -> {
PolarisSDKContextManager manager = context.getBean(PolarisSDKContextManager.class);
LocationConfigImpl locationConfig = (LocationConfigImpl) manager.getSDKContext()
.getConfig().getGlobal().getLocation();
long cloudProviderCount = locationConfig.getProviders().stream()
.filter(p -> LocationProvider.ProviderType.CLOUD.getName().equals(p.getType()))
.count();
assertThat(cloudProviderCount).isEqualTo(1);
});
}
/**
* Test purpose: verify getOrder returns the location order constant.
* Test scenario: obtain modifier bean from context and call getOrder.
* Verification: order equals OrderConstant.Modifier.LOCATION_ORDER.
*/
@DisplayName("getOrder returns LOCATION_ORDER")
@Test
void testGetOrder() {
enabledContextRunner.run(context -> {
PolarisLocationConfigModifier modifier = context.getBean(PolarisLocationConfigModifier.class);
assertThat(modifier.getOrder()).isEqualTo(OrderConstant.Modifier.LOCATION_ORDER);
});
}
@SpringBootApplication
protected static class TestApplication {
}
}

@ -0,0 +1,104 @@
/*
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
*
* Copyright (C) 2021 Tencent. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.tencent.cloud.polaris.context.config.location;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Test for {@link PolarisLocationProperties}.
*
* @author Haotian Zhang
*/
@DisplayName("PolarisLocationProperties")
class PolarisLocationPropertiesTest {
/**
* Test purpose: verify PolarisLocationProperties default values.
* Test scenario: no configuration provided, use default constructor.
* Verification: cloud.enabled is true by default.
*/
@DisplayName("cloud.enabled defaults to true")
@Test
void testDefaultCloudEnabled() {
// Arrange
PolarisLocationProperties properties = new PolarisLocationProperties();
// Act & Assert
assertThat(properties.getCloud().isEnabled()).isTrue();
}
/**
* Test purpose: verify PolarisLocationProperties.Cloud setter and getter.
* Test scenario: set cloud.enabled to false via setter.
* Verification: getter returns false.
*/
@DisplayName("Cloud enabled can be set to false")
@Test
void testSetCloudEnabled() {
// Arrange
PolarisLocationProperties properties = new PolarisLocationProperties();
PolarisLocationProperties.Cloud cloud = new PolarisLocationProperties.Cloud();
cloud.setEnabled(false);
// Act
properties.setCloud(cloud);
// Assert
assertThat(properties.getCloud().isEnabled()).isFalse();
}
/**
* Test purpose: verify PolarisLocationProperties toString output.
* Test scenario: default properties instance.
* Verification: toString contains cloud and enabled info.
*/
@DisplayName("toString contains cloud info")
@Test
void testToString() {
// Arrange
PolarisLocationProperties properties = new PolarisLocationProperties();
// Act
String result = properties.toString();
// Assert
assertThat(result).contains("cloud=");
assertThat(result).contains("enabled=true");
}
/**
* Test purpose: verify PolarisLocationProperties.Cloud toString output.
* Test scenario: default Cloud instance.
* Verification: toString contains enabled=true.
*/
@DisplayName("Cloud toString contains enabled info")
@Test
void testCloudToString() {
// Arrange
PolarisLocationProperties.Cloud cloud = new PolarisLocationProperties.Cloud();
// Act
String result = cloud.toString();
// Assert
assertThat(result).contains("enabled=true");
}
}
Loading…
Cancel
Save