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> Signed-off-by: Haotian Zhang <928016560@qq.com>pull/1802/head
parent
90941e2de9
commit
2ce72028b3
@ -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…
Reference in new issue