Skip to content

Commit

Permalink
feat:add zero protection. (Tencent#1278)
Browse files Browse the repository at this point in the history
* feat:add zero protection.

* feat:add zero protection.

* feat:add zero protection.

* feat:add zero protection.

* feat:add zero protection.

* feat:add zero protection.

* feat:add zero protection.

* feat:add zero protection.

* feat:add zero protection.

* feat:add zero protection.

* feat:add zero protection.
  • Loading branch information
SkyeBeFreeman authored and fuyuwei01 committed Aug 14, 2024
1 parent 50d4b55 commit 18032d7
Show file tree
Hide file tree
Showing 24 changed files with 305 additions and 41 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@
- [fix: fix grammar issues for lane router example & optimize the gateway dependency](https://github.com/Tencent/spring-cloud-tencent/pull/1382)
- [refactor:let the configuration SDK context stand alone.](https://github.com/Tencent/spring-cloud-tencent/pull/1383)
- [fix: fix lossless deregister failed when no healthcheck configured](https://github.com/Tencent/spring-cloud-tencent/pull/1385)
- [fix:fix ApplicationContextAwareUtils NPE bug.](https://github.com/Tencent/spring-cloud-tencent/pull/1386)
- [fix:fix ApplicationContextAwareUtils NPE bug.](https://github.com/Tencent/spring-cloud-tencent/pull/1386)
- [feat:add zero protection.](https://github.com/Tencent/spring-cloud-tencent/pull/1278)
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@ public ConfigurationModifier(PolarisConfigProperties polarisConfigProperties,

@Override
public void modify(ConfigurationImpl configuration) {
configuration.getGlobal().getAPI().setReportEnable(false);

if (!polarisContextProperties.getEnabled() || !polarisConfigProperties.isEnabled()) {
return;
}
if (StringUtils.equalsIgnoreCase(polarisConfigProperties.getDataSource(), DATA_SOURCE_POLARIS)) {
initByPolarisDataSource(configuration);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,23 +78,26 @@ public PolarisConfigFileLocator(PolarisConfigProperties polarisConfigProperties,

@Override
public PropertySource<?> locate(Environment environment) {
CompositePropertySource compositePropertySource = new CompositePropertySource(POLARIS_CONFIG_PROPERTY_SOURCE_NAME);
try {
// load custom config extension files
initCustomPolarisConfigExtensionFiles(compositePropertySource);
// load spring boot default config files
initInternalConfigFiles(compositePropertySource);
// load custom config files
List<ConfigFileGroup> configFileGroups = polarisConfigProperties.getGroups();
if (CollectionUtils.isEmpty(configFileGroups)) {
if (polarisConfigProperties.isEnabled()) {
CompositePropertySource compositePropertySource = new CompositePropertySource(POLARIS_CONFIG_PROPERTY_SOURCE_NAME);
try {
// load custom config extension files
initCustomPolarisConfigExtensionFiles(compositePropertySource);
// load spring boot default config files
initInternalConfigFiles(compositePropertySource);
// load custom config files
List<ConfigFileGroup> configFileGroups = polarisConfigProperties.getGroups();
if (CollectionUtils.isEmpty(configFileGroups)) {
return compositePropertySource;
}
initCustomPolarisConfigFiles(compositePropertySource, configFileGroups);
return compositePropertySource;
}
initCustomPolarisConfigFiles(compositePropertySource, configFileGroups);
return compositePropertySource;
}
finally {
afterLocatePolarisConfigExtension(compositePropertySource);
finally {
afterLocatePolarisConfigExtension(compositePropertySource);
}
}
return null;
}

private void initCustomPolarisConfigExtensionFiles(CompositePropertySource compositePropertySource) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ public void testLoadApplicationPropertiesFile() {
when(configFileService.getConfigYamlFile(testNamespace, testServiceName, "bootstrap.yml")).thenReturn(emptyConfigFile);
when(configFileService.getConfigYamlFile(testNamespace, testServiceName, "bootstrap.yaml")).thenReturn(emptyConfigFile);

when(polarisConfigProperties.isEnabled()).thenReturn(true);
when(polarisConfigProperties.getGroups()).thenReturn(null);
when(environment.getActiveProfiles()).thenReturn(new String[] {});

Expand Down Expand Up @@ -137,6 +138,7 @@ public void testActiveProfileFilesPriorityBiggerThanDefault() {
when(configFileService.getConfigYamlFile(testNamespace, testServiceName, "bootstrap-dev.yml")).thenReturn(emptyConfigFile);
when(configFileService.getConfigYamlFile(testNamespace, testServiceName, "bootstrap-dev.yaml")).thenReturn(emptyConfigFile);

when(polarisConfigProperties.isEnabled()).thenReturn(true);
when(polarisConfigProperties.getGroups()).thenReturn(null);
when(environment.getActiveProfiles()).thenReturn(new String[] {"dev"});

Expand Down Expand Up @@ -174,6 +176,7 @@ public void testGetCustomFiles() {
configFileGroup.setFiles(Lists.newArrayList(customFile1, customFile2));
customFiles.add(configFileGroup);

when(polarisConfigProperties.isEnabled()).thenReturn(true);
when(polarisConfigProperties.getGroups()).thenReturn(customFiles);
when(environment.getActiveProfiles()).thenReturn(new String[] {});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,22 @@

package com.tencent.cloud.polaris.contract;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.tencent.cloud.common.util.JacksonUtils;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.tencent.cloud.common.util.GzipUtil;
import com.tencent.cloud.polaris.PolarisDiscoveryProperties;
import com.tencent.cloud.polaris.contract.config.PolarisContractProperties;
import com.tencent.polaris.api.core.ProviderAPI;
import com.tencent.polaris.api.plugin.server.InterfaceDescriptor;
import com.tencent.polaris.api.plugin.server.ReportServiceContractRequest;
import com.tencent.polaris.api.plugin.server.ReportServiceContractResponse;
import com.tencent.polaris.api.utils.StringUtils;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.Operation;
import io.swagger.v3.oas.models.PathItem;
Expand All @@ -37,6 +41,7 @@
import org.slf4j.LoggerFactory;
import org.springdoc.api.AbstractOpenApiResource;
import org.springdoc.api.AbstractOpenApiResourceUtil;
import org.springdoc.core.providers.ObjectMapperProvider;
import org.springdoc.webflux.api.OpenApiWebFluxUtil;
import org.springdoc.webmvc.api.OpenApiWebMvcUtil;

Expand All @@ -62,15 +67,18 @@ public class PolarisContractReporter implements ApplicationListener<ApplicationR

private final PolarisDiscoveryProperties polarisDiscoveryProperties;

private final ObjectMapperProvider springdocObjectMapperProvider;

public PolarisContractReporter(org.springdoc.webmvc.api.MultipleOpenApiResource multipleOpenApiWebMvcResource,
org.springdoc.webflux.api.MultipleOpenApiResource multipleOpenApiWebFluxResource,
PolarisContractProperties polarisContractProperties, ProviderAPI providerAPI,
PolarisDiscoveryProperties polarisDiscoveryProperties) {
PolarisDiscoveryProperties polarisDiscoveryProperties, ObjectMapperProvider springdocObjectMapperProvider) {
this.multipleOpenApiWebMvcResource = multipleOpenApiWebMvcResource;
this.multipleOpenApiWebFluxResource = multipleOpenApiWebFluxResource;
this.polarisContractProperties = polarisContractProperties;
this.providerAPI = providerAPI;
this.polarisDiscoveryProperties = polarisDiscoveryProperties;
this.springdocObjectMapperProvider = springdocObjectMapperProvider;
}

@Override
Expand All @@ -90,20 +98,35 @@ else if (multipleOpenApiWebFluxResource != null) {
}
if (openAPI != null) {
ReportServiceContractRequest request = new ReportServiceContractRequest();
request.setName(polarisDiscoveryProperties.getService());
String name = polarisContractProperties.getName();
if (StringUtils.isBlank(name)) {
name = polarisDiscoveryProperties.getService();
}
request.setName(name);
request.setNamespace(polarisDiscoveryProperties.getNamespace());
request.setService(polarisDiscoveryProperties.getService());
request.setProtocol("http");
request.setVersion(polarisDiscoveryProperties.getVersion());
List<InterfaceDescriptor> interfaceDescriptorList = getInterfaceDescriptorFromSwagger(openAPI);
request.setInterfaceDescriptors(interfaceDescriptorList);
String jsonValue;
if (springdocObjectMapperProvider != null && springdocObjectMapperProvider.jsonMapper() != null) {
jsonValue = springdocObjectMapperProvider.jsonMapper().writeValueAsString(openAPI);
}
else {
ObjectMapper mapper = new ObjectMapper();
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
jsonValue = mapper.writeValueAsString(openAPI);
}
String serviceApiMeta = GzipUtil.compressBase64Encode(jsonValue, "utf-8");
request.setContent(serviceApiMeta);
ReportServiceContractResponse response = providerAPI.reportServiceContract(request);
LOG.info("Service contract [Namespace: {}. Name: {}. Service: {}. Protocol:{}. Version: {}. API counter: {}] is reported.",
request.getNamespace(), request.getName(), request.getService(), request.getProtocol(),
request.getVersion(), request.getInterfaceDescriptors().size());
if (LOG.isDebugEnabled()) {
String jsonValue = JacksonUtils.serialize2Json(openAPI);
LOG.debug("OpenApi json data: {}", jsonValue);
LOG.debug("OpenApi json base64 data: {}", serviceApiMeta);
}
}
else {
Expand All @@ -129,7 +152,21 @@ private List<InterfaceDescriptor> getInterfaceDescriptorFromSwagger(OpenAPI open
InterfaceDescriptor interfaceDescriptor = new InterfaceDescriptor();
interfaceDescriptor.setPath(p.getKey());
interfaceDescriptor.setMethod(o.getKey());
interfaceDescriptor.setContent(JacksonUtils.serialize2Json(p.getValue()));
try {
String jsonValue;
if (springdocObjectMapperProvider != null && springdocObjectMapperProvider.jsonMapper() != null) {
jsonValue = springdocObjectMapperProvider.jsonMapper().writeValueAsString(o.getValue());
}
else {
ObjectMapper mapper = new ObjectMapper();
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
jsonValue = mapper.writeValueAsString(o.getValue());
}
interfaceDescriptor.setContent(GzipUtil.compressBase64Encode(jsonValue, "utf-8"));
}
catch (IOException ioe) {
LOG.warn("Encode operation [{}] failed.", o.getValue(), ioe);
}
interfaceDescriptorList.add(interfaceDescriptor);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,8 @@ public interface ContractProperties {
boolean isReportEnabled();

void setReportEnabled(boolean reportEnabled);

String getName();

void setName(String name);
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ public PolarisContractModifier(PolarisContractProperties polarisContractProperti
public void modify(ConfigurationImpl configuration) {
List<RegisterConfigImpl> registerConfigs = configuration.getProvider().getRegisters();
for (RegisterConfigImpl registerConfig : registerConfigs) {
registerConfig.setReportServiceContractEnable(polarisContractProperties.isEnabled());
registerConfig.setReportServiceContractEnable(
polarisContractProperties.isEnabled() && polarisContractProperties.isReportEnabled());
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ public class PolarisContractProperties implements ContractProperties {
@Value("${spring.cloud.polaris.contract.report.enabled:true}")
private boolean reportEnabled = true;

private String name;

public PolarisContractProperties(@Nullable ExtendedContractProperties extendContractProperties) {
this.extendContractProperties = extendContractProperties;
}
Expand All @@ -71,6 +73,9 @@ public boolean isEnabled() {

@Override
public void setEnabled(boolean enabled) {
if (Objects.nonNull(extendContractProperties)) {
extendContractProperties.setEnabled(enabled);
}
this.enabled = enabled;
}

Expand All @@ -84,6 +89,9 @@ public String getBasePackage() {

@Override
public void setBasePackage(String basePackage) {
if (Objects.nonNull(extendContractProperties)) {
extendContractProperties.setBasePackage(basePackage);
}
this.basePackage = basePackage;
}

Expand All @@ -97,6 +105,9 @@ public String getExcludePath() {

@Override
public void setExcludePath(String excludePath) {
if (Objects.nonNull(extendContractProperties)) {
extendContractProperties.setExcludePath(excludePath);
}
this.excludePath = excludePath;
}

Expand All @@ -110,6 +121,9 @@ public String getGroup() {

@Override
public void setGroup(String group) {
if (Objects.nonNull(extendContractProperties)) {
extendContractProperties.setGroup(group);
}
this.group = group;
}

Expand All @@ -123,6 +137,9 @@ public String getBasePath() {

@Override
public void setBasePath(String basePath) {
if (Objects.nonNull(extendContractProperties)) {
extendContractProperties.setBasePath(basePath);
}
this.basePath = basePath;
}

Expand All @@ -136,16 +153,40 @@ public boolean isExposure() {

@Override
public void setExposure(boolean exposure) {
if (Objects.nonNull(extendContractProperties)) {
extendContractProperties.setExposure(exposure);
}
this.exposure = exposure;
}

@Override
public boolean isReportEnabled() {
if (Objects.nonNull(extendContractProperties)) {
return extendContractProperties.isReportEnabled();
}
return reportEnabled;
}

@Override
public void setReportEnabled(boolean reportEnabled) {
if (Objects.nonNull(extendContractProperties)) {
extendContractProperties.setReportEnabled(reportEnabled);
}
this.reportEnabled = reportEnabled;
}

public String getName() {
if (Objects.nonNull(extendContractProperties)) {
return extendContractProperties.getName();
}
return name;
}

@Override
public void setName(String name) {
if (Objects.nonNull(extendContractProperties)) {
extendContractProperties.setName(name);
}
this.name = name;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import io.swagger.v3.oas.models.info.License;
import org.springdoc.core.GroupedOpenApi;
import org.springdoc.core.SpringDocConfiguration;
import org.springdoc.core.providers.ObjectMapperProvider;
import org.springdoc.webflux.api.MultipleOpenApiWebFluxResource;
import org.springdoc.webmvc.api.MultipleOpenApiWebMvcResource;

Expand All @@ -56,6 +57,12 @@
@Import(SpringDocConfiguration.class)
public class PolarisSwaggerAutoConfiguration {

static {
// After springboot2.6.x, the default path matching strategy of spring MVC is changed from ANT_PATH_MATCHER
// mode to PATH_PATTERN_PARSER mode, causing an error. The solution is to switch to the original ANT_PATH_MATCHER mode.
System.setProperty("spring.mvc.pathmatch.matching-strategy", "ant-path-matcher");
}

@Bean
public GroupedOpenApi polarisGroupedOpenApi(PolarisContractProperties polarisContractProperties) {
String basePackage = PackageUtil.scanPackage(polarisContractProperties.getBasePackage());
Expand All @@ -79,8 +86,8 @@ public GroupedOpenApi polarisGroupedOpenApi(PolarisContractProperties polarisCon
public OpenAPI polarisOpenAPI() {
return new OpenAPI()
.info(new Info()
.title("Polaris Swagger API")
.description("This is to show polaris api description.")
.title("Polaris Contract")
.description("This is to show polaris contract description.")
.license(new License().name("BSD-3-Clause").url("https://opensource.org/licenses/BSD-3-Clause"))
.version("1.0.0"));
}
Expand All @@ -92,9 +99,9 @@ public PolarisContractReporter polarisContractReporter(
@Nullable MultipleOpenApiWebMvcResource multipleOpenApiWebMvcResource,
@Nullable MultipleOpenApiWebFluxResource multipleOpenApiWebFluxResource,
PolarisContractProperties polarisContractProperties, PolarisSDKContextManager polarisSDKContextManager,
PolarisDiscoveryProperties polarisDiscoveryProperties) {
PolarisDiscoveryProperties polarisDiscoveryProperties, ObjectMapperProvider springdocObjectMapperProvider) {
return new PolarisContractReporter(multipleOpenApiWebMvcResource, multipleOpenApiWebFluxResource,
polarisContractProperties, polarisSDKContextManager.getProviderAPI(), polarisDiscoveryProperties);
polarisContractProperties, polarisSDKContextManager.getProviderAPI(), polarisDiscoveryProperties, springdocObjectMapperProvider);
}

@Bean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.tencent.cloud.polaris.contract.config.PolarisSwaggerAutoConfiguration,\
com.tencent.cloud.polaris.contract.config.PolarisContractProperties
org.springframework.cloud.bootstrap.BootstrapConfiguration=\
com.tencent.cloud.polaris.contract.config.PolarisContractPropertiesAutoConfiguration
com.tencent.cloud.polaris.contract.config.PolarisContractPropertiesBootstrapConfiguration
org.springframework.context.ApplicationListener=\
com.tencent.cloud.polaris.contract.PolarisSwaggerApplicationListener
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ public void modify(ConfigurationImpl configuration) {
// Set ServiceRefreshInterval
configuration.getConsumer().getLocalCache()
.setServiceListRefreshInterval(polarisDiscoveryProperties.getServiceListRefreshInterval());

configuration.getConsumer().getZeroProtection().setEnable(polarisDiscoveryProperties.isZeroProtectionEnabled());
configuration.getConsumer().getZeroProtection()
.setNeedTestConnectivity(polarisDiscoveryProperties.isZeroProtectionNeedTestConnectivity());
}

@Override
Expand Down
Loading

0 comments on commit 18032d7

Please sign in to comment.