From 60bb8a7c2ccea0f056d3754dbe95d85562353778 Mon Sep 17 00:00:00 2001 From: wulingxiao <1251605638@qqcom> Date: Sun, 17 Jul 2022 20:13:08 +0800 Subject: [PATCH] feature:support spring cloud configData --- .../adapter/PolarisConfigFileLocator.java | 2 +- .../adapter/PolarisConfigFilePuller.java | 2 +- .../configdata/PolarisConfigDataLoader.java | 7 +- ...igDataMissingEnvironmentPostProcessor.java | 45 +++ ...PolarisImportExceptionFailureAnalyzer.java | 32 ++ ...itional-spring-configuration-metadata.json | 6 + .../main/resources/META-INF/spring.factories | 5 + .../adapter/PolarisConfigFilePullerTest.java | 310 ++++++++++++++++++ .../PolarisConfigDataLoaderTest.java | 270 +++++++++++++++ ...PolarisConfigDataLocationResolverTest.java | 10 + ...taMissingEnvironmentPostProcessorTest.java | 88 +++++ ...risImportExceptionFailureAnalyzerTest.java | 35 ++ 12 files changed, 808 insertions(+), 4 deletions(-) create mode 100644 spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/configdata/PolarisConfigDataMissingEnvironmentPostProcessor.java create mode 100644 spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/configdata/PolarisImportExceptionFailureAnalyzer.java create mode 100644 spring-cloud-starter-tencent-polaris-config/src/test/java/com/tencent/cloud/polaris/config/adapter/PolarisConfigFilePullerTest.java create mode 100644 spring-cloud-starter-tencent-polaris-config/src/test/java/com/tencent/cloud/polaris/config/configdata/PolarisConfigDataLoaderTest.java create mode 100644 spring-cloud-starter-tencent-polaris-config/src/test/java/com/tencent/cloud/polaris/config/configdata/PolarisConfigDataLocationResolverTest.java create mode 100644 spring-cloud-starter-tencent-polaris-config/src/test/java/com/tencent/cloud/polaris/config/configdata/PolarisConfigDataMissingEnvironmentPostProcessorTest.java create mode 100644 spring-cloud-starter-tencent-polaris-config/src/test/java/com/tencent/cloud/polaris/config/configdata/PolarisImportExceptionFailureAnalyzerTest.java diff --git a/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/adapter/PolarisConfigFileLocator.java b/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/adapter/PolarisConfigFileLocator.java index 7479d761a..e0d7b3eff 100644 --- a/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/adapter/PolarisConfigFileLocator.java +++ b/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/adapter/PolarisConfigFileLocator.java @@ -51,7 +51,7 @@ public class PolarisConfigFileLocator implements PropertySourceLocator { PolarisContextProperties polarisContextProperties, ConfigFileService configFileService, PolarisPropertySourceManager polarisPropertySourceManager, Environment environment) { this.polarisConfigProperties = polarisConfigProperties; - this.polarisConfigFilePuller = new PolarisConfigFilePuller(polarisContextProperties, configFileService, + this.polarisConfigFilePuller = PolarisConfigFilePuller.get(polarisContextProperties, configFileService, polarisPropertySourceManager, environment); } diff --git a/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/adapter/PolarisConfigFilePuller.java b/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/adapter/PolarisConfigFilePuller.java index 078e53db5..bc9c1627c 100644 --- a/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/adapter/PolarisConfigFilePuller.java +++ b/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/adapter/PolarisConfigFilePuller.java @@ -1 +1 @@ -/* * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. * * Copyright (C) 2019 THL A29 Limited, a Tencent company. 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.config.adapter; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; import com.google.common.collect.Lists; import com.tencent.cloud.polaris.config.config.ConfigFileGroup; import com.tencent.cloud.polaris.config.enums.ConfigFileFormat; import com.tencent.cloud.polaris.context.config.PolarisContextProperties; import com.tencent.polaris.configuration.api.core.ConfigFileMetadata; import com.tencent.polaris.configuration.api.core.ConfigFileService; import com.tencent.polaris.configuration.api.core.ConfigKVFile; import com.tencent.polaris.configuration.client.internal.DefaultConfigFileMetadata; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.context.config.Profiles; import org.springframework.core.env.CompositePropertySource; import org.springframework.core.env.Environment; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; /** * PolarisConfigFilePuller pull configFile from Polaris. * * @author wlx */ public class PolarisConfigFilePuller { private static final Logger LOGGER = LoggerFactory.getLogger(PolarisConfigFileLocator.class); private final PolarisContextProperties polarisContextProperties; private final ConfigFileService configFileService; private final PolarisPropertySourceManager polarisPropertySourceManager; private Environment environment; public PolarisConfigFilePuller(PolarisContextProperties polarisContextProperties, ConfigFileService configFileService, PolarisPropertySourceManager polarisPropertySourceManager, Environment environment) { this.polarisContextProperties = polarisContextProperties; this.configFileService = configFileService; this.polarisPropertySourceManager = polarisPropertySourceManager; this.environment = environment; } public PolarisConfigFilePuller(PolarisContextProperties polarisContextProperties, ConfigFileService configFileService, PolarisPropertySourceManager polarisPropertySourceManager) { this.polarisContextProperties = polarisContextProperties; this.configFileService = configFileService; this.polarisPropertySourceManager = polarisPropertySourceManager; } public void initInternalConfigFiles(CompositePropertySource compositePropertySource) { List internalConfigFiles = getInternalConfigFiles(); for (ConfigFileMetadata configFile : internalConfigFiles) { PolarisPropertySource polarisPropertySource = loadPolarisPropertySource( configFile.getNamespace(), configFile.getFileGroup(), configFile.getFileName()); compositePropertySource.addPropertySource(polarisPropertySource); polarisPropertySourceManager.addPropertySource(polarisPropertySource); LOGGER.info("[SCT Config] Load and inject polaris config file. file = {}", configFile); } } public void initInternalConfigFiles(CompositePropertySource compositePropertySource, Profiles profiles, String serviceName) { List internalConfigFiles = getInternalConfigFiles(profiles, serviceName); for (ConfigFileMetadata configFile : internalConfigFiles) { PolarisPropertySource polarisPropertySource = loadPolarisPropertySource( configFile.getNamespace(), configFile.getFileGroup(), configFile.getFileName()); compositePropertySource.addPropertySource(polarisPropertySource); polarisPropertySourceManager.addPropertySource(polarisPropertySource); LOGGER.info("[SCT Config] Load and inject polaris config file. file = {}", configFile); } } public void initCustomPolarisConfigFiles(CompositePropertySource compositePropertySource, List configFileGroups) { configFileGroups.forEach( configFileGroup -> initCustomPolarisConfigFile(compositePropertySource, configFileGroup) ); } public void initCustomPolarisConfigFile(CompositePropertySource compositePropertySource, ConfigFileGroup configFileGroup) { String namespace = polarisContextProperties.getNamespace(); String group = configFileGroup.getName(); if (!StringUtils.hasText(group)) { throw new IllegalArgumentException("polaris config group name cannot be empty."); } List files = configFileGroup.getFiles(); if (CollectionUtils.isEmpty(files)) { return; } for (String fileName : files) { PolarisPropertySource polarisPropertySource = loadPolarisPropertySource(namespace, group, fileName); compositePropertySource.addPropertySource(polarisPropertySource); polarisPropertySourceManager.addPropertySource(polarisPropertySource); LOGGER.info( "[SCT Config] Load and inject polaris config file success. namespace = {}, group = {}, fileName = {}", namespace, group, fileName); } } private PolarisPropertySource loadPolarisPropertySource(String namespace, String group, String fileName) { ConfigKVFile configKVFile; // unknown extension is resolved as properties file if (ConfigFileFormat.isPropertyFile(fileName) || ConfigFileFormat.isUnknownFile(fileName)) { configKVFile = configFileService.getConfigPropertiesFile(namespace, group, fileName); } else if (ConfigFileFormat.isYamlFile(fileName)) { configKVFile = configFileService.getConfigYamlFile(namespace, group, fileName); } else { LOGGER.warn("[SCT Config] Unsupported config file. namespace = {}, group = {}, fileName = {}", namespace, group, fileName); throw new IllegalStateException("Only configuration files in the format of properties / yaml / yaml" + " can be injected into the spring context"); } Map map = new ConcurrentHashMap<>(); for (String key : configKVFile.getPropertyNames()) { map.put(key, configKVFile.getProperty(key, null)); } return new PolarisPropertySource(namespace, group, fileName, configKVFile, map); } private List getInternalConfigFiles() { String namespace = polarisContextProperties.getNamespace(); String serviceName = polarisContextProperties.getService(); if (Objects.isNull(this.environment)) { return Lists.newArrayList(); } if (!StringUtils.hasText(serviceName)) { serviceName = environment.getProperty("spring.application.name"); } // priority: application-${profile} > application > boostrap-${profile} > boostrap String[] activeProfiles = environment.getActiveProfiles(); return getInternalConfigFiles(activeProfiles, namespace, serviceName); } private List getInternalConfigFiles(Profiles profiles, String serviceName) { String namespace = polarisContextProperties.getNamespace(); if (StringUtils.hasText(polarisContextProperties.getService())) { serviceName = polarisContextProperties.getService(); } // priority: application-${profile} > application > boostrap-${profile} > boostrap List active = profiles.getActive(); String[] activeProfiles = active.toArray(new String[]{}); return getInternalConfigFiles(activeProfiles, namespace, serviceName); } private List getInternalConfigFiles(String[] activeProfiles, String namespace, String serviceName) { List internalConfigFiles = new LinkedList<>(); for (String activeProfile : activeProfiles) { if (!StringUtils.hasText(activeProfile)) { continue; } internalConfigFiles.add(new DefaultConfigFileMetadata(namespace, serviceName, "application-" + activeProfile + ".properties")); internalConfigFiles.add(new DefaultConfigFileMetadata(namespace, serviceName, "application-" + activeProfile + ".yml")); } internalConfigFiles.add(new DefaultConfigFileMetadata(namespace, serviceName, "application.properties")); internalConfigFiles.add(new DefaultConfigFileMetadata(namespace, serviceName, "application.yml")); for (String activeProfile : activeProfiles) { if (!StringUtils.hasText(activeProfile)) { continue; } internalConfigFiles.add(new DefaultConfigFileMetadata(namespace, serviceName, "bootstrap-" + activeProfile + ".properties")); internalConfigFiles.add(new DefaultConfigFileMetadata(namespace, serviceName, "bootstrap-" + activeProfile + ".yml")); } internalConfigFiles.add(new DefaultConfigFileMetadata(namespace, serviceName, "bootstrap.properties")); internalConfigFiles.add(new DefaultConfigFileMetadata(namespace, serviceName, "bootstrap.yml")); return internalConfigFiles; } } \ No newline at end of file +/* * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. * * Copyright (C) 2019 THL A29 Limited, a Tencent company. 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.config.adapter; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; import com.google.common.collect.Lists; import com.tencent.cloud.polaris.config.config.ConfigFileGroup; import com.tencent.cloud.polaris.config.configdata.PolarisConfigDataLoader; import com.tencent.cloud.polaris.config.enums.ConfigFileFormat; import com.tencent.cloud.polaris.context.config.PolarisContextProperties; import com.tencent.polaris.configuration.api.core.ConfigFileMetadata; import com.tencent.polaris.configuration.api.core.ConfigFileService; import com.tencent.polaris.configuration.api.core.ConfigKVFile; import com.tencent.polaris.configuration.client.internal.DefaultConfigFileMetadata; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.context.config.Profiles; import org.springframework.core.env.CompositePropertySource; import org.springframework.core.env.Environment; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; /** * PolarisConfigFilePuller pull configFile from Polaris. * * @author wlx */ public final class PolarisConfigFilePuller { private static final Logger LOGGER = LoggerFactory.getLogger(PolarisConfigFileLocator.class); private PolarisContextProperties polarisContextProperties; private ConfigFileService configFileService; private PolarisPropertySourceManager polarisPropertySourceManager; private Environment environment; private PolarisConfigFilePuller() { } /** * InitInternalConfigFiles for {@link PolarisConfigFileLocator}. * * @param compositePropertySource compositePropertySource */ public void initInternalConfigFiles(CompositePropertySource compositePropertySource) { List internalConfigFiles = getInternalConfigFiles(); for (ConfigFileMetadata configFile : internalConfigFiles) { PolarisPropertySource polarisPropertySource = loadPolarisPropertySource( configFile.getNamespace(), configFile.getFileGroup(), configFile.getFileName()); compositePropertySource.addPropertySource(polarisPropertySource); polarisPropertySourceManager.addPropertySource(polarisPropertySource); LOGGER.info("[SCT Config] Load and inject polaris config file. file = {}", configFile); } } /** * InitInternalConfigFiles for {@link PolarisConfigDataLoader}. * * @param compositePropertySource compositePropertySource * @param profiles profiles * @param serviceName serviceName */ public void initInternalConfigFiles(CompositePropertySource compositePropertySource, Profiles profiles, String serviceName) { List internalConfigFiles = getInternalConfigFiles(profiles, serviceName); for (ConfigFileMetadata configFile : internalConfigFiles) { PolarisPropertySource polarisPropertySource = loadPolarisPropertySource( configFile.getNamespace(), configFile.getFileGroup(), configFile.getFileName()); compositePropertySource.addPropertySource(polarisPropertySource); polarisPropertySourceManager.addPropertySource(polarisPropertySource); LOGGER.info("[SCT Config] Load and inject polaris config file. file = {}", configFile); } } /** * Init multiple CustomPolarisConfigFile. * * @param compositePropertySource compositePropertySource * @param configFileGroups configFileGroups */ public void initCustomPolarisConfigFiles(CompositePropertySource compositePropertySource, List configFileGroups) { configFileGroups.forEach( configFileGroup -> initCustomPolarisConfigFile(compositePropertySource, configFileGroup) ); } /** * Init single CustomPolarisConfigFile. * * @param compositePropertySource compositePropertySource * @param configFileGroup configFileGroup */ public void initCustomPolarisConfigFile(CompositePropertySource compositePropertySource, ConfigFileGroup configFileGroup) { String namespace = polarisContextProperties.getNamespace(); String group = configFileGroup.getName(); if (!StringUtils.hasText(group)) { throw new IllegalArgumentException("polaris config group name cannot be empty."); } List files = configFileGroup.getFiles(); if (CollectionUtils.isEmpty(files)) { return; } for (String fileName : files) { PolarisPropertySource polarisPropertySource = loadPolarisPropertySource(namespace, group, fileName); compositePropertySource.addPropertySource(polarisPropertySource); polarisPropertySourceManager.addPropertySource(polarisPropertySource); LOGGER.info( "[SCT Config] Load and inject polaris config file success. namespace = {}, group = {}, fileName = {}", namespace, group, fileName); } } private PolarisPropertySource loadPolarisPropertySource(String namespace, String group, String fileName) { ConfigKVFile configKVFile; // unknown extension is resolved as properties file if (ConfigFileFormat.isPropertyFile(fileName) || ConfigFileFormat.isUnknownFile(fileName)) { configKVFile = configFileService.getConfigPropertiesFile(namespace, group, fileName); } else if (ConfigFileFormat.isYamlFile(fileName)) { configKVFile = configFileService.getConfigYamlFile(namespace, group, fileName); } else { LOGGER.warn("[SCT Config] Unsupported config file. namespace = {}, group = {}, fileName = {}", namespace, group, fileName); throw new IllegalStateException("Only configuration files in the format of properties / yaml / yaml" + " can be injected into the spring context"); } Map map = new ConcurrentHashMap<>(); for (String key : configKVFile.getPropertyNames()) { map.put(key, configKVFile.getProperty(key, null)); } return new PolarisPropertySource(namespace, group, fileName, configKVFile, map); } private List getInternalConfigFiles() { String namespace = polarisContextProperties.getNamespace(); String serviceName = polarisContextProperties.getService(); if (Objects.isNull(this.environment)) { return Lists.newArrayList(); } if (!StringUtils.hasText(serviceName)) { serviceName = environment.getProperty("spring.application.name"); } // priority: application-${profile} > application > boostrap-${profile} > boostrap String[] activeProfiles = environment.getActiveProfiles(); return getInternalConfigFiles(activeProfiles, namespace, serviceName); } private List getInternalConfigFiles(Profiles profiles, String serviceName) { String namespace = polarisContextProperties.getNamespace(); if (StringUtils.hasText(polarisContextProperties.getService())) { serviceName = polarisContextProperties.getService(); } // priority: application-${profile} > application > boostrap-${profile} > boostrap List active = profiles.getActive(); String[] activeProfiles = active.toArray(new String[]{}); return getInternalConfigFiles(activeProfiles, namespace, serviceName); } private List getInternalConfigFiles(String[] activeProfiles, String namespace, String serviceName) { List internalConfigFiles = new LinkedList<>(); for (String activeProfile : activeProfiles) { if (!StringUtils.hasText(activeProfile)) { continue; } internalConfigFiles.add(new DefaultConfigFileMetadata(namespace, serviceName, "application-" + activeProfile + ".properties")); internalConfigFiles.add(new DefaultConfigFileMetadata(namespace, serviceName, "application-" + activeProfile + ".yml")); } internalConfigFiles.add(new DefaultConfigFileMetadata(namespace, serviceName, "application.properties")); internalConfigFiles.add(new DefaultConfigFileMetadata(namespace, serviceName, "application.yml")); for (String activeProfile : activeProfiles) { if (!StringUtils.hasText(activeProfile)) { continue; } internalConfigFiles.add(new DefaultConfigFileMetadata(namespace, serviceName, "bootstrap-" + activeProfile + ".properties")); internalConfigFiles.add(new DefaultConfigFileMetadata(namespace, serviceName, "bootstrap-" + activeProfile + ".yml")); } internalConfigFiles.add(new DefaultConfigFileMetadata(namespace, serviceName, "bootstrap.properties")); internalConfigFiles.add(new DefaultConfigFileMetadata(namespace, serviceName, "bootstrap.yml")); return internalConfigFiles; } /** * Factory method to create PolarisConfigFilePuller for * {@link PolarisConfigFileLocator}. * * @param polarisContextProperties polarisContextProperties * @param configFileService configFileService * @param polarisPropertySourceManager polarisPropertySourceManager * @param environment environment * @return PolarisConfigFilePuller instance */ public static PolarisConfigFilePuller get(PolarisContextProperties polarisContextProperties, ConfigFileService configFileService, PolarisPropertySourceManager polarisPropertySourceManager, Environment environment) { PolarisConfigFilePuller puller = new PolarisConfigFilePuller(); puller.polarisContextProperties = polarisContextProperties; puller.configFileService = configFileService; puller.polarisPropertySourceManager = polarisPropertySourceManager; puller.environment = environment; return puller; } /** * Factory method to create PolarisConfigFilePuller for * {@link PolarisConfigDataLoader}. * * @param polarisContextProperties polarisContextProperties * @param configFileService configFileService * @param polarisPropertySourceManager polarisPropertySourceManager * @return PolarisConfigFilePuller instance */ public static PolarisConfigFilePuller get(PolarisContextProperties polarisContextProperties, ConfigFileService configFileService, PolarisPropertySourceManager polarisPropertySourceManager) { PolarisConfigFilePuller puller = new PolarisConfigFilePuller(); puller.polarisContextProperties = polarisContextProperties; puller.configFileService = configFileService; puller.polarisPropertySourceManager = polarisPropertySourceManager; return puller; } } \ No newline at end of file diff --git a/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/configdata/PolarisConfigDataLoader.java b/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/configdata/PolarisConfigDataLoader.java index 627f675ca..f9477c7d9 100644 --- a/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/configdata/PolarisConfigDataLoader.java +++ b/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/configdata/PolarisConfigDataLoader.java @@ -38,6 +38,7 @@ import org.springframework.boot.context.config.ConfigDataResourceNotFoundExcepti import org.springframework.boot.context.config.Profiles; import org.springframework.boot.logging.DeferredLogFactory; import org.springframework.core.env.CompositePropertySource; +import org.springframework.core.env.PropertySource; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; @@ -89,7 +90,9 @@ public class PolarisConfigDataLoader implements ConfigDataLoader> propertySources = new ArrayList<>(); + propertySources.add(compositePropertySource); + return new ConfigData(propertySources, getOptions(resource)); } private CompositePropertySource locate(ConfigurableBootstrapContext bootstrapContext, @@ -101,7 +104,7 @@ public class PolarisConfigDataLoader implements ConfigDataLoader { + + @Override + protected FailureAnalysis analyze(Throwable rootFailure, ConfigDataMissingEnvironmentPostProcessor.ImportException cause) { + String description; + if (cause.missingPrefix) { + description = "The spring.config.import property is missing a " + PolarisConfigDataLocationResolver.PREFIX + + " entry"; + } + else { + description = "No spring.config.import property has been defined"; + } + String action = "Add a spring.config.import=polaris property to your configuration.\n" + + "\tIf configuration is not required add spring.config.import=optional:polaris instead.\n" + + "\tTo disable this check, set spring.cloud.polaris.config.import-check.enabled=false."; + return new FailureAnalysis(description, action, cause); + } +} diff --git a/spring-cloud-starter-tencent-polaris-config/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/spring-cloud-starter-tencent-polaris-config/src/main/resources/META-INF/additional-spring-configuration-metadata.json index 9954a62ce..75bc4907e 100644 --- a/spring-cloud-starter-tencent-polaris-config/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ b/spring-cloud-starter-tencent-polaris-config/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -41,6 +41,12 @@ "defaultValue": "true", "description": "Whether to connect to a remote server, suitable for local development mode.", "sourceType": "com.tencent.cloud.polaris.config.config.PolarisConfigProperties" + }, + { + "name": "spring.cloud.polaris.config.import-check.enabled", + "type": "java.lang.Boolean", + "defaultValue": true, + "description": "Whether to enable import-check." } ] } diff --git a/spring-cloud-starter-tencent-polaris-config/src/main/resources/META-INF/spring.factories b/spring-cloud-starter-tencent-polaris-config/src/main/resources/META-INF/spring.factories index 8926927cc..d51d4f589 100644 --- a/spring-cloud-starter-tencent-polaris-config/src/main/resources/META-INF/spring.factories +++ b/spring-cloud-starter-tencent-polaris-config/src/main/resources/META-INF/spring.factories @@ -11,3 +11,8 @@ org.springframework.boot.context.config.ConfigDataLocationResolver=\ # ConfigData Loaders org.springframework.boot.context.config.ConfigDataLoader=\ com.tencent.cloud.polaris.config.configdata.PolarisConfigDataLoader +org.springframework.boot.diagnostics.FailureAnalyzer=\ + com.tencent.cloud.polaris.config.configdata.PolarisImportExceptionFailureAnalyzer +org.springframework.boot.env.EnvironmentPostProcessor=\ + com.tencent.cloud.polaris.config.configdata.PolarisConfigDataMissingEnvironmentPostProcessor + diff --git a/spring-cloud-starter-tencent-polaris-config/src/test/java/com/tencent/cloud/polaris/config/adapter/PolarisConfigFilePullerTest.java b/spring-cloud-starter-tencent-polaris-config/src/test/java/com/tencent/cloud/polaris/config/adapter/PolarisConfigFilePullerTest.java new file mode 100644 index 000000000..2dcaa412d --- /dev/null +++ b/spring-cloud-starter-tencent-polaris-config/src/test/java/com/tencent/cloud/polaris/config/adapter/PolarisConfigFilePullerTest.java @@ -0,0 +1,310 @@ +package com.tencent.cloud.polaris.config.adapter; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import com.google.common.collect.Lists; +import com.tencent.cloud.polaris.config.config.ConfigFileGroup; +import com.tencent.cloud.polaris.config.config.PolarisConfigProperties; +import com.tencent.cloud.polaris.context.config.PolarisContextProperties; +import com.tencent.polaris.configuration.api.core.ConfigFileService; +import com.tencent.polaris.configuration.api.core.ConfigKVFile; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; + +import org.springframework.boot.context.config.Profiles; +import org.springframework.core.env.CompositePropertySource; +import org.springframework.core.env.Environment; + +import static org.mockito.Mockito.when; + +/** + * Test for {@link PolarisConfigFilePuller}. + * + * @author wlx + */ +@RunWith(MockitoJUnitRunner.class) +public class PolarisConfigFilePullerTest { + + @Mock + private PolarisConfigProperties polarisConfigProperties; + @Mock + private PolarisContextProperties polarisContextProperties; + @Mock + private ConfigFileService configFileService; + @Mock + private PolarisPropertySourceManager polarisPropertySourceManager; + @Mock + private Environment environment; + @Mock + private Profiles profiles; + + private final String testNamespace = "testNamespace"; + private final String testServiceName = "testServiceName"; + private final String polarisConfigPropertySourceName = "polaris-config"; + + @Test + public void testBootstrapPullInternalConfigFiles() { + PolarisConfigFilePuller puller = PolarisConfigFilePuller.get(polarisContextProperties, configFileService, + polarisPropertySourceManager, environment); + + when(polarisContextProperties.getNamespace()).thenReturn(testNamespace); + when(polarisContextProperties.getService()).thenReturn(testServiceName); + + // application.properties + Map applicationProperties = new HashMap<>(); + applicationProperties.put("k1", "v1"); + applicationProperties.put("k2", "v2"); + applicationProperties.put("k3", "v3"); + ConfigKVFile propertiesFile = new MockedConfigKVFile(applicationProperties); + when(configFileService.getConfigPropertiesFile(testNamespace, testServiceName, "application.properties")) + .thenReturn(propertiesFile); + + Map emptyMap = new HashMap<>(); + ConfigKVFile emptyConfigFile = new MockedConfigKVFile(emptyMap); + when(configFileService.getConfigYamlFile(testNamespace, testServiceName, "application.yml")).thenReturn(emptyConfigFile); + when(configFileService.getConfigPropertiesFile(testNamespace, testServiceName, "bootstrap.properties")).thenReturn(emptyConfigFile); + when(configFileService.getConfigYamlFile(testNamespace, testServiceName, "bootstrap.yml")).thenReturn(emptyConfigFile); + + when(polarisConfigProperties.getGroups()).thenReturn(null); + when(environment.getActiveProfiles()).thenReturn(new String[]{}); + + CompositePropertySource compositePropertySource = new CompositePropertySource(polarisConfigPropertySourceName); + puller.initInternalConfigFiles(compositePropertySource); + + Assert.assertEquals("v1", compositePropertySource.getProperty("k1")); + Assert.assertEquals("v2", compositePropertySource.getProperty("k2")); + Assert.assertEquals("v3", compositePropertySource.getProperty("k3")); + } + + @Test + public void testBootstrapPullInternalConfigFilesWithProfile() { + PolarisConfigFilePuller puller = PolarisConfigFilePuller.get(polarisContextProperties, configFileService, + polarisPropertySourceManager, environment); + + when(polarisContextProperties.getNamespace()).thenReturn(testNamespace); + when(polarisContextProperties.getService()).thenReturn(testServiceName); + + // application.properties + Map applicationProperties = new HashMap<>(); + applicationProperties.put("k1", "v1"); + applicationProperties.put("k2", "v2"); + applicationProperties.put("k3", "v3"); + ConfigKVFile propertiesFile = new MockedConfigKVFile(applicationProperties); + when(configFileService.getConfigPropertiesFile(testNamespace, testServiceName, "application.properties")) + .thenReturn(propertiesFile); + + // application-dev.properties + Map devProperties = new HashMap<>(); + devProperties.put("k1", "v11"); + ConfigKVFile devFile = new MockedConfigKVFile(devProperties); + when(configFileService.getConfigPropertiesFile(testNamespace, testServiceName, "application-dev.properties")) + .thenReturn(devFile); + + Map emptyMap = new HashMap<>(); + ConfigKVFile emptyConfigFile = new MockedConfigKVFile(emptyMap); + when(configFileService.getConfigYamlFile(testNamespace, testServiceName, "application.yml")).thenReturn(emptyConfigFile); + when(configFileService.getConfigYamlFile(testNamespace, testServiceName, "application-dev.yml")).thenReturn(emptyConfigFile); + when(configFileService.getConfigPropertiesFile(testNamespace, testServiceName, "bootstrap.properties")).thenReturn(emptyConfigFile); + when(configFileService.getConfigPropertiesFile(testNamespace, testServiceName, "bootstrap-dev.properties")).thenReturn(emptyConfigFile); + when(configFileService.getConfigYamlFile(testNamespace, testServiceName, "bootstrap.yml")).thenReturn(emptyConfigFile); + when(configFileService.getConfigYamlFile(testNamespace, testServiceName, "bootstrap-dev.yml")).thenReturn(emptyConfigFile); + + when(polarisConfigProperties.getGroups()).thenReturn(null); + when(environment.getActiveProfiles()).thenReturn(new String[]{"dev"}); + + CompositePropertySource compositePropertySource = new CompositePropertySource(polarisConfigPropertySourceName); + puller.initInternalConfigFiles(compositePropertySource); + + Assert.assertEquals("v11", compositePropertySource.getProperty("k1")); + Assert.assertEquals("v2", compositePropertySource.getProperty("k2")); + Assert.assertEquals("v3", compositePropertySource.getProperty("k3")); + } + + @Test + public void testBootstrapPullCustomConfigFilesWithProfile() { + PolarisConfigFilePuller puller = PolarisConfigFilePuller.get(polarisContextProperties, configFileService, + polarisPropertySourceManager, environment); + + when(polarisContextProperties.getNamespace()).thenReturn(testNamespace); + when(polarisContextProperties.getService()).thenReturn(testServiceName); + + Map emptyMap = new HashMap<>(); + ConfigKVFile emptyConfigFile = new MockedConfigKVFile(emptyMap); + + when(configFileService.getConfigPropertiesFile(testNamespace, testServiceName, "application.properties")).thenReturn(emptyConfigFile); + when(configFileService.getConfigYamlFile(testNamespace, testServiceName, "application.yml")).thenReturn(emptyConfigFile); + when(configFileService.getConfigPropertiesFile(testNamespace, testServiceName, "bootstrap.properties")).thenReturn(emptyConfigFile); + when(configFileService.getConfigYamlFile(testNamespace, testServiceName, "bootstrap.yml")).thenReturn(emptyConfigFile); + + List customFiles = new LinkedList<>(); + ConfigFileGroup configFileGroup = new ConfigFileGroup(); + String customGroup = "group1"; + configFileGroup.setName(customGroup); + String customFile1 = "file1.properties"; + String customFile2 = "file2.properties"; + configFileGroup.setFiles(Lists.newArrayList(customFile1, customFile2)); + customFiles.add(configFileGroup); + + when(polarisConfigProperties.getGroups()).thenReturn(customFiles); + when(environment.getActiveProfiles()).thenReturn(new String[]{}); + + // file1.properties + Map file1Map = new HashMap<>(); + file1Map.put("k1", "v1"); + file1Map.put("k2", "v2"); + ConfigKVFile file1 = new MockedConfigKVFile(file1Map); + when(configFileService.getConfigPropertiesFile(testNamespace, customGroup, customFile1)).thenReturn(file1); + + // file2.properties + Map file2Map = new HashMap<>(); + file2Map.put("k1", "v11"); + file2Map.put("k3", "v3"); + ConfigKVFile file2 = new MockedConfigKVFile(file2Map); + when(configFileService.getConfigPropertiesFile(testNamespace, customGroup, customFile2)).thenReturn(file2); + + CompositePropertySource compositePropertySource = new CompositePropertySource(polarisConfigPropertySourceName); + puller.initCustomPolarisConfigFiles(compositePropertySource, customFiles); + + Assert.assertEquals("v1", compositePropertySource.getProperty("k1")); + Assert.assertEquals("v2", compositePropertySource.getProperty("k2")); + Assert.assertEquals("v3", compositePropertySource.getProperty("k3")); + } + + @Test + public void testConfigDataPullInternalConfigFiles() { + PolarisConfigFilePuller puller = PolarisConfigFilePuller.get(polarisContextProperties, configFileService, + polarisPropertySourceManager); + + when(polarisContextProperties.getNamespace()).thenReturn(testNamespace); + when(polarisContextProperties.getService()).thenReturn(testServiceName); + + // application.properties + Map applicationProperties = new HashMap<>(); + applicationProperties.put("k1", "v1"); + applicationProperties.put("k2", "v2"); + applicationProperties.put("k3", "v3"); + ConfigKVFile propertiesFile = new MockedConfigKVFile(applicationProperties); + when(configFileService.getConfigPropertiesFile(testNamespace, testServiceName, "application.properties")) + .thenReturn(propertiesFile); + + Map emptyMap = new HashMap<>(); + ConfigKVFile emptyConfigFile = new MockedConfigKVFile(emptyMap); + when(configFileService.getConfigYamlFile(testNamespace, testServiceName, "application.yml")).thenReturn(emptyConfigFile); + when(configFileService.getConfigPropertiesFile(testNamespace, testServiceName, "bootstrap.properties")).thenReturn(emptyConfigFile); + when(configFileService.getConfigYamlFile(testNamespace, testServiceName, "bootstrap.yml")).thenReturn(emptyConfigFile); + + when(polarisConfigProperties.getGroups()).thenReturn(null); + + when(profiles.getActive()).thenReturn(Lists.newArrayList()); + + CompositePropertySource compositePropertySource = new CompositePropertySource(polarisConfigPropertySourceName); + puller.initInternalConfigFiles(compositePropertySource, profiles, testServiceName); + + Assert.assertEquals("v1", compositePropertySource.getProperty("k1")); + Assert.assertEquals("v2", compositePropertySource.getProperty("k2")); + Assert.assertEquals("v3", compositePropertySource.getProperty("k3")); + } + + @Test + public void testConfigDataPullInternalConfigFilesWithProfile() { + PolarisConfigFilePuller puller = PolarisConfigFilePuller.get(polarisContextProperties, configFileService, + polarisPropertySourceManager); + + when(polarisContextProperties.getNamespace()).thenReturn(testNamespace); + when(polarisContextProperties.getService()).thenReturn(testServiceName); + + // application.properties + Map applicationProperties = new HashMap<>(); + applicationProperties.put("k1", "v1"); + applicationProperties.put("k2", "v2"); + applicationProperties.put("k3", "v3"); + ConfigKVFile propertiesFile = new MockedConfigKVFile(applicationProperties); + when(configFileService.getConfigPropertiesFile(testNamespace, testServiceName, "application.properties")) + .thenReturn(propertiesFile); + + // application-dev.properties + Map devProperties = new HashMap<>(); + devProperties.put("k1", "v11"); + ConfigKVFile devFile = new MockedConfigKVFile(devProperties); + when(configFileService.getConfigPropertiesFile(testNamespace, testServiceName, "application-dev.properties")) + .thenReturn(devFile); + + Map emptyMap = new HashMap<>(); + ConfigKVFile emptyConfigFile = new MockedConfigKVFile(emptyMap); + when(configFileService.getConfigYamlFile(testNamespace, testServiceName, "application.yml")).thenReturn(emptyConfigFile); + when(configFileService.getConfigYamlFile(testNamespace, testServiceName, "application-dev.yml")).thenReturn(emptyConfigFile); + when(configFileService.getConfigPropertiesFile(testNamespace, testServiceName, "bootstrap.properties")).thenReturn(emptyConfigFile); + when(configFileService.getConfigPropertiesFile(testNamespace, testServiceName, "bootstrap-dev.properties")).thenReturn(emptyConfigFile); + when(configFileService.getConfigYamlFile(testNamespace, testServiceName, "bootstrap.yml")).thenReturn(emptyConfigFile); + when(configFileService.getConfigYamlFile(testNamespace, testServiceName, "bootstrap-dev.yml")).thenReturn(emptyConfigFile); + + when(polarisConfigProperties.getGroups()).thenReturn(null); + List active = new ArrayList<>(); + active.add("dev"); + when(profiles.getActive()).thenReturn(active); + + CompositePropertySource compositePropertySource = new CompositePropertySource(polarisConfigPropertySourceName); + puller.initInternalConfigFiles(compositePropertySource, profiles, testServiceName); + + Assert.assertEquals("v11", compositePropertySource.getProperty("k1")); + Assert.assertEquals("v2", compositePropertySource.getProperty("k2")); + Assert.assertEquals("v3", compositePropertySource.getProperty("k3")); + } + + @Test + public void testConfigDataPullCustomConfigFilesWithProfile() { + PolarisConfigFilePuller puller = PolarisConfigFilePuller.get(polarisContextProperties, configFileService, + polarisPropertySourceManager); + + when(polarisContextProperties.getNamespace()).thenReturn(testNamespace); + when(polarisContextProperties.getService()).thenReturn(testServiceName); + + Map emptyMap = new HashMap<>(); + ConfigKVFile emptyConfigFile = new MockedConfigKVFile(emptyMap); + + when(configFileService.getConfigPropertiesFile(testNamespace, testServiceName, "application.properties")).thenReturn(emptyConfigFile); + when(configFileService.getConfigYamlFile(testNamespace, testServiceName, "application.yml")).thenReturn(emptyConfigFile); + when(configFileService.getConfigPropertiesFile(testNamespace, testServiceName, "bootstrap.properties")).thenReturn(emptyConfigFile); + when(configFileService.getConfigYamlFile(testNamespace, testServiceName, "bootstrap.yml")).thenReturn(emptyConfigFile); + + List customFiles = new LinkedList<>(); + ConfigFileGroup configFileGroup = new ConfigFileGroup(); + String customGroup = "group1"; + configFileGroup.setName(customGroup); + String customFile1 = "file1.properties"; + String customFile2 = "file2.properties"; + configFileGroup.setFiles(Lists.newArrayList(customFile1, customFile2)); + customFiles.add(configFileGroup); + + when(polarisConfigProperties.getGroups()).thenReturn(customFiles); + when(profiles.getActive()).thenReturn(Lists.newArrayList()); + + // file1.properties + Map file1Map = new HashMap<>(); + file1Map.put("k1", "v1"); + file1Map.put("k2", "v2"); + ConfigKVFile file1 = new MockedConfigKVFile(file1Map); + when(configFileService.getConfigPropertiesFile(testNamespace, customGroup, customFile1)).thenReturn(file1); + + // file2.properties + Map file2Map = new HashMap<>(); + file2Map.put("k1", "v11"); + file2Map.put("k3", "v3"); + ConfigKVFile file2 = new MockedConfigKVFile(file2Map); + when(configFileService.getConfigPropertiesFile(testNamespace, customGroup, customFile2)).thenReturn(file2); + + CompositePropertySource compositePropertySource = new CompositePropertySource(polarisConfigPropertySourceName); + puller.initCustomPolarisConfigFiles(compositePropertySource, customFiles); + + Assert.assertEquals("v1", compositePropertySource.getProperty("k1")); + Assert.assertEquals("v2", compositePropertySource.getProperty("k2")); + Assert.assertEquals("v3", compositePropertySource.getProperty("k3")); + } +} diff --git a/spring-cloud-starter-tencent-polaris-config/src/test/java/com/tencent/cloud/polaris/config/configdata/PolarisConfigDataLoaderTest.java b/spring-cloud-starter-tencent-polaris-config/src/test/java/com/tencent/cloud/polaris/config/configdata/PolarisConfigDataLoaderTest.java new file mode 100644 index 000000000..0897f0600 --- /dev/null +++ b/spring-cloud-starter-tencent-polaris-config/src/test/java/com/tencent/cloud/polaris/config/configdata/PolarisConfigDataLoaderTest.java @@ -0,0 +1,270 @@ +package com.tencent.cloud.polaris.config.configdata; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import com.google.common.collect.Lists; +import com.tencent.cloud.polaris.config.adapter.MockedConfigKVFile; +import com.tencent.cloud.polaris.config.adapter.PolarisPropertySourceManager; +import com.tencent.cloud.polaris.config.config.PolarisConfigProperties; +import com.tencent.cloud.polaris.context.config.PolarisContextProperties; +import com.tencent.polaris.client.api.SDKContext; +import com.tencent.polaris.configuration.api.core.ConfigFileService; +import com.tencent.polaris.configuration.api.core.ConfigKVFile; +import com.tencent.polaris.configuration.factory.ConfigFileServiceFactory; +import org.junit.Assert; +import org.junit.Test; +import org.junit.jupiter.api.AfterAll; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockedStatic; +import org.mockito.junit.MockitoJUnitRunner; + +import org.springframework.boot.ConfigurableBootstrapContext; +import org.springframework.boot.context.config.ConfigData; +import org.springframework.boot.context.config.ConfigDataLoaderContext; +import org.springframework.boot.context.config.Profiles; +import org.springframework.boot.logging.DeferredLogs; +import org.springframework.core.env.CompositePropertySource; +import org.springframework.core.env.PropertySource; + +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.when; + +/** + * Test for {@link PolarisConfigDataLoader}. + * + * @author wlx + * @date 2022/7/16 4:09 下午 + */ +@RunWith(MockitoJUnitRunner.class) +public class PolarisConfigDataLoaderTest { + + @Mock + private ConfigDataLoaderContext context; + @Mock + private PolarisConfigDataResource polarisConfigDataResource; + @Mock + private ConfigurableBootstrapContext bootstrapContext; + @Mock + private PolarisConfigProperties polarisConfigProperties; + @Mock + private PolarisContextProperties polarisContextProperties; + @Mock + private ConfigFileService configFileService; + @Mock + private Profiles profiles; + + private static SDKContext sdkContext; + + private final String testNamespace = "testNamespace"; + private final String testServiceName = "testServiceName"; + + @Test + public void loadConfigDataInternalConfigFilesTest() { + try (MockedStatic mockedStatic = mockStatic(ConfigFileServiceFactory.class)) { + Map emptyMap = new HashMap<>(); + ConfigKVFile emptyConfigFile = new MockedConfigKVFile(emptyMap); + when(configFileService.getConfigYamlFile(testNamespace, testServiceName, "application.yml")).thenReturn(emptyConfigFile); + when(configFileService.getConfigPropertiesFile(testNamespace, testServiceName, "bootstrap.properties")).thenReturn(emptyConfigFile); + when(configFileService.getConfigYamlFile(testNamespace, testServiceName, "bootstrap.yml")).thenReturn(emptyConfigFile); + Map applicationProperties = new HashMap<>(); + applicationProperties.put("k1", "v1"); + applicationProperties.put("k2", "v2"); + applicationProperties.put("k3", "v3"); + ConfigKVFile propertiesFile = new MockedConfigKVFile(applicationProperties); + when(configFileService.getConfigPropertiesFile(testNamespace, testServiceName, "application.properties")) + .thenReturn(propertiesFile); + + mockSDKContext(); + when(context.getBootstrapContext()).thenReturn(bootstrapContext); + when(bootstrapContext.isRegistered(eq(SDKContext.class))).thenReturn(false); + when(bootstrapContext.get(eq(SDKContext.class))).thenReturn(sdkContext); + + when(bootstrapContext.isRegistered(eq(PolarisPropertySourceManager.class))).thenReturn(false); + when(bootstrapContext.get(eq(PolarisPropertySourceManager.class))).thenReturn(new PolarisPropertySourceManager()); + + when(polarisContextProperties.getNamespace()).thenReturn(testNamespace); + when(polarisContextProperties.getService()).thenReturn(testServiceName); + + when(polarisConfigProperties.getGroups()).thenReturn(null); + when(profiles.getActive()).thenReturn(Lists.newArrayList()); + + PolarisConfigDataLoader polarisConfigDataLoader = new PolarisConfigDataLoader(new DeferredLogs()); + when(polarisConfigDataResource.getPolarisConfigProperties()).thenReturn(polarisConfigProperties); + when(polarisConfigDataResource.getPolarisContextProperties()).thenReturn(polarisContextProperties); + when(polarisConfigDataResource.getServiceName()).thenReturn(testServiceName); + when(polarisConfigDataResource.getProfiles()).thenReturn(profiles); + + mockedStatic.when(() -> { + ConfigFileServiceFactory.createConfigFileService(sdkContext); + }).thenReturn(this.configFileService); + + ConfigData configData = polarisConfigDataLoader.load(context, polarisConfigDataResource); + List> propertySources = configData.getPropertySources(); + Optional> propertySource = propertySources.stream().findFirst(); + if (propertySource.isPresent()) { + PropertySource source = propertySource.get(); + Assert.assertTrue(source instanceof CompositePropertySource); + CompositePropertySource compositePropertySource = (CompositePropertySource) source; + Assert.assertEquals("v1", compositePropertySource.getProperty("k1")); + Assert.assertEquals("v2", compositePropertySource.getProperty("k2")); + Assert.assertEquals("v3", compositePropertySource.getProperty("k3")); + } + } + } + + @Test + public void loadConfigDataInternalConfigFilesTestWithProfile() { + try (MockedStatic mockedStatic = mockStatic(ConfigFileServiceFactory.class)) { + Map applicationProperties = new HashMap<>(); + applicationProperties.put("k1", "v1"); + applicationProperties.put("k2", "v2"); + applicationProperties.put("k3", "v3"); + ConfigKVFile propertiesFile = new MockedConfigKVFile(applicationProperties); + when(configFileService.getConfigPropertiesFile(testNamespace, testServiceName, "application.properties")) + .thenReturn(propertiesFile); + + // application-dev.properties + Map devProperties = new HashMap<>(); + devProperties.put("k1", "v11"); + ConfigKVFile devFile = new MockedConfigKVFile(devProperties); + when(configFileService.getConfigPropertiesFile(testNamespace, testServiceName, "application-dev.properties")) + .thenReturn(devFile); + + Map emptyMap = new HashMap<>(); + ConfigKVFile emptyConfigFile = new MockedConfigKVFile(emptyMap); + when(configFileService.getConfigYamlFile(testNamespace, testServiceName, "application.yml")).thenReturn(emptyConfigFile); + when(configFileService.getConfigYamlFile(testNamespace, testServiceName, "application-dev.yml")).thenReturn(emptyConfigFile); + when(configFileService.getConfigPropertiesFile(testNamespace, testServiceName, "bootstrap.properties")).thenReturn(emptyConfigFile); + when(configFileService.getConfigPropertiesFile(testNamespace, testServiceName, "bootstrap-dev.properties")).thenReturn(emptyConfigFile); + when(configFileService.getConfigYamlFile(testNamespace, testServiceName, "bootstrap.yml")).thenReturn(emptyConfigFile); + when(configFileService.getConfigYamlFile(testNamespace, testServiceName, "bootstrap-dev.yml")).thenReturn(emptyConfigFile); + + when(polarisConfigProperties.getGroups()).thenReturn(null); + when(polarisConfigProperties.getGroups()).thenReturn(null); + List active = new ArrayList<>(); + active.add("dev"); + when(profiles.getActive()).thenReturn(active); + + mockSDKContext(); + when(context.getBootstrapContext()).thenReturn(bootstrapContext); + when(bootstrapContext.isRegistered(eq(SDKContext.class))).thenReturn(false); + when(bootstrapContext.get(eq(SDKContext.class))).thenReturn(sdkContext); + + when(bootstrapContext.isRegistered(eq(PolarisPropertySourceManager.class))).thenReturn(false); + when(bootstrapContext.get(eq(PolarisPropertySourceManager.class))).thenReturn(new PolarisPropertySourceManager()); + + when(polarisContextProperties.getNamespace()).thenReturn(testNamespace); + when(polarisContextProperties.getService()).thenReturn(testServiceName); + + when(polarisConfigProperties.getGroups()).thenReturn(null); + + PolarisConfigDataLoader polarisConfigDataLoader = new PolarisConfigDataLoader(new DeferredLogs()); + when(polarisConfigDataResource.getPolarisConfigProperties()).thenReturn(polarisConfigProperties); + when(polarisConfigDataResource.getPolarisContextProperties()).thenReturn(polarisContextProperties); + when(polarisConfigDataResource.getServiceName()).thenReturn(testServiceName); + when(polarisConfigDataResource.getProfiles()).thenReturn(profiles); + + + mockedStatic.when(() -> { + ConfigFileServiceFactory.createConfigFileService(sdkContext); + }).thenReturn(this.configFileService); + + ConfigData configData = polarisConfigDataLoader.load(context, polarisConfigDataResource); + List> propertySources = configData.getPropertySources(); + Optional> propertySource = propertySources.stream().findFirst(); + if (propertySource.isPresent()) { + PropertySource source = propertySource.get(); + Assert.assertTrue(source instanceof CompositePropertySource); + CompositePropertySource compositePropertySource = (CompositePropertySource) source; + Assert.assertEquals("v11", compositePropertySource.getProperty("k1")); + Assert.assertEquals("v2", compositePropertySource.getProperty("k2")); + Assert.assertEquals("v3", compositePropertySource.getProperty("k3")); + } + } + } + + @Test + public void loadConfigDataCustomConfigFilesTestWithProfile() { + try (MockedStatic mockedStatic = mockStatic(ConfigFileServiceFactory.class)) { + Map emptyMap = new HashMap<>(); + ConfigKVFile emptyConfigFile = new MockedConfigKVFile(emptyMap); + + when(configFileService.getConfigPropertiesFile(testNamespace, testServiceName, "application.properties")).thenReturn(emptyConfigFile); + when(configFileService.getConfigYamlFile(testNamespace, testServiceName, "application.yml")).thenReturn(emptyConfigFile); + when(configFileService.getConfigPropertiesFile(testNamespace, testServiceName, "bootstrap.properties")).thenReturn(emptyConfigFile); + when(configFileService.getConfigYamlFile(testNamespace, testServiceName, "bootstrap.yml")).thenReturn(emptyConfigFile); + + String customGroup = "group1"; + String customFile1 = "file1.properties"; + when(polarisConfigDataResource.getFileName()).thenReturn(customFile1); + when(polarisConfigDataResource.getGroupName()).thenReturn(customGroup); + + when(polarisConfigProperties.getGroups()).thenReturn(null); + when(profiles.getActive()).thenReturn(Lists.newArrayList()); + + // file1.properties + Map file1Map = new HashMap<>(); + file1Map.put("k1", "v1"); + file1Map.put("k2", "v2"); + file1Map.put("k3", "v3"); + ConfigKVFile file1 = new MockedConfigKVFile(file1Map); + when(configFileService.getConfigPropertiesFile(testNamespace, customGroup, customFile1)).thenReturn(file1); + + + mockSDKContext(); + when(context.getBootstrapContext()).thenReturn(bootstrapContext); + when(bootstrapContext.isRegistered(eq(SDKContext.class))).thenReturn(false); + when(bootstrapContext.get(eq(SDKContext.class))).thenReturn(sdkContext); + + when(bootstrapContext.isRegistered(eq(PolarisPropertySourceManager.class))).thenReturn(false); + when(bootstrapContext.get(eq(PolarisPropertySourceManager.class))).thenReturn(new PolarisPropertySourceManager()); + + when(polarisContextProperties.getNamespace()).thenReturn(testNamespace); + when(polarisContextProperties.getService()).thenReturn(testServiceName); + + when(polarisConfigProperties.getGroups()).thenReturn(null); + when(profiles.getActive()).thenReturn(Lists.newArrayList()); + + PolarisConfigDataLoader polarisConfigDataLoader = new PolarisConfigDataLoader(new DeferredLogs()); + when(polarisConfigDataResource.getPolarisConfigProperties()).thenReturn(polarisConfigProperties); + when(polarisConfigDataResource.getPolarisContextProperties()).thenReturn(polarisContextProperties); + when(polarisConfigDataResource.getServiceName()).thenReturn(testServiceName); + when(polarisConfigDataResource.getProfiles()).thenReturn(profiles); + + mockedStatic.when(() -> { + ConfigFileServiceFactory.createConfigFileService(sdkContext); + }).thenReturn(this.configFileService); + + ConfigData configData = polarisConfigDataLoader.load(context, polarisConfigDataResource); + List> propertySources = configData.getPropertySources(); + Optional> propertySource = propertySources.stream().findFirst(); + if (propertySource.isPresent()) { + PropertySource source = propertySource.get(); + Assert.assertTrue(source instanceof CompositePropertySource); + CompositePropertySource compositePropertySource = (CompositePropertySource) source; + Assert.assertEquals("v1", compositePropertySource.getProperty("k1")); + Assert.assertEquals("v2", compositePropertySource.getProperty("k2")); + Assert.assertEquals("v3", compositePropertySource.getProperty("k3")); + } + } + } + + @AfterAll + static void afterAll() { + if (sdkContext != null) { + sdkContext.destroy(); + } + } + + private void mockSDKContext() { + if (sdkContext == null) { + sdkContext = SDKContext.initContext(); + } + } +} diff --git a/spring-cloud-starter-tencent-polaris-config/src/test/java/com/tencent/cloud/polaris/config/configdata/PolarisConfigDataLocationResolverTest.java b/spring-cloud-starter-tencent-polaris-config/src/test/java/com/tencent/cloud/polaris/config/configdata/PolarisConfigDataLocationResolverTest.java new file mode 100644 index 000000000..4a21afd2e --- /dev/null +++ b/spring-cloud-starter-tencent-polaris-config/src/test/java/com/tencent/cloud/polaris/config/configdata/PolarisConfigDataLocationResolverTest.java @@ -0,0 +1,10 @@ +package com.tencent.cloud.polaris.config.configdata; + +/** + * Test for {@link PolarisConfigDataLocationResolver}. + * + * @author wlx + * @date 2022/7/16 4:10 下午 + */ +public class PolarisConfigDataLocationResolverTest { +} diff --git a/spring-cloud-starter-tencent-polaris-config/src/test/java/com/tencent/cloud/polaris/config/configdata/PolarisConfigDataMissingEnvironmentPostProcessorTest.java b/spring-cloud-starter-tencent-polaris-config/src/test/java/com/tencent/cloud/polaris/config/configdata/PolarisConfigDataMissingEnvironmentPostProcessorTest.java new file mode 100644 index 000000000..2d69fc67f --- /dev/null +++ b/spring-cloud-starter-tencent-polaris-config/src/test/java/com/tencent/cloud/polaris/config/configdata/PolarisConfigDataMissingEnvironmentPostProcessorTest.java @@ -0,0 +1,88 @@ +package com.tencent.cloud.polaris.config.configdata; + +import org.junit.Test; + +import org.springframework.boot.SpringApplication; +import org.springframework.mock.env.MockEnvironment; + +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.Mockito.mock; + +/** + * Test for {@link PolarisConfigDataMissingEnvironmentPostProcessor}. + * + * @author wlx + * @date 2022/7/16 4:09 下午 + */ +public class PolarisConfigDataMissingEnvironmentPostProcessorTest { + + @Test + public void missConfigData() { + MockEnvironment environment = new MockEnvironment(); + SpringApplication app = mock(SpringApplication.class); + PolarisConfigDataMissingEnvironmentPostProcessor processor = new PolarisConfigDataMissingEnvironmentPostProcessor(); + assertThatThrownBy(() -> processor.postProcessEnvironment(environment, app)) + .isInstanceOf(PolarisConfigDataMissingEnvironmentPostProcessor.ImportException.class); + } + + @Test + public void bootstrapEnabledTest() { + MockEnvironment environment = new MockEnvironment(); + environment.setProperty("spring.cloud.bootstrap.enabled", "true"); + SpringApplication app = mock(SpringApplication.class); + PolarisConfigDataMissingEnvironmentPostProcessor processor = new PolarisConfigDataMissingEnvironmentPostProcessor(); + // if bootstrap enabled,don't throw ImportException + assertThatCode(() -> processor.postProcessEnvironment(environment, app)).doesNotThrowAnyException(); + } + + @Test + public void legacyProcessingTest() { + MockEnvironment environment = new MockEnvironment(); + environment.setProperty("spring.config.use-legacy-processing", "true"); + SpringApplication app = mock(SpringApplication.class); + PolarisConfigDataMissingEnvironmentPostProcessor processor = new PolarisConfigDataMissingEnvironmentPostProcessor(); + // if use-legacy-processing,don't throw ImportException + assertThatCode(() -> processor.postProcessEnvironment(environment, app)).doesNotThrowAnyException(); + } + + @Test + public void closeImportCheck() { + MockEnvironment environment = new MockEnvironment(); + environment.setProperty("spring.cloud.polaris.config.import-check.enabled", "false"); + SpringApplication app = mock(SpringApplication.class); + PolarisConfigDataMissingEnvironmentPostProcessor processor = new PolarisConfigDataMissingEnvironmentPostProcessor(); + // if import-check.enabled is false,don't throw ImportException + assertThatCode(() -> processor.postProcessEnvironment(environment, app)).doesNotThrowAnyException(); + } + + @Test + public void closePolarisConfig() { + MockEnvironment environment = new MockEnvironment(); + environment.setProperty("spring.cloud.polaris.config.enabled", "false"); + SpringApplication app = mock(SpringApplication.class); + PolarisConfigDataMissingEnvironmentPostProcessor processor = new PolarisConfigDataMissingEnvironmentPostProcessor(); + // if polaris.config is false,don't throw ImportException + assertThatCode(() -> processor.postProcessEnvironment(environment, app)).doesNotThrowAnyException(); + } + + @Test + public void normalConfigDataImport() { + MockEnvironment environment = new MockEnvironment(); + environment.setProperty("spring.config.import", "polaris"); + SpringApplication app = mock(SpringApplication.class); + PolarisConfigDataMissingEnvironmentPostProcessor processor = new PolarisConfigDataMissingEnvironmentPostProcessor(); + // config polaris config import ,don't throw ImportException + assertThatCode(() -> processor.postProcessEnvironment(environment, app)).doesNotThrowAnyException(); + } + + @Test + public void importOtherConfigDataWithoutPolaris() { + MockEnvironment environment = new MockEnvironment(); + environment.setProperty("spring.config.import", "file:application.properties"); + SpringApplication app = mock(SpringApplication.class); + PolarisConfigDataMissingEnvironmentPostProcessor processor = new PolarisConfigDataMissingEnvironmentPostProcessor(); + assertThatThrownBy(() -> processor.postProcessEnvironment(environment, app)) + .isInstanceOf(PolarisConfigDataMissingEnvironmentPostProcessor.ImportException.class); + } +} diff --git a/spring-cloud-starter-tencent-polaris-config/src/test/java/com/tencent/cloud/polaris/config/configdata/PolarisImportExceptionFailureAnalyzerTest.java b/spring-cloud-starter-tencent-polaris-config/src/test/java/com/tencent/cloud/polaris/config/configdata/PolarisImportExceptionFailureAnalyzerTest.java new file mode 100644 index 000000000..dd8269ca6 --- /dev/null +++ b/spring-cloud-starter-tencent-polaris-config/src/test/java/com/tencent/cloud/polaris/config/configdata/PolarisImportExceptionFailureAnalyzerTest.java @@ -0,0 +1,35 @@ +package com.tencent.cloud.polaris.config.configdata; + +import com.tencent.polaris.api.utils.StringUtils; +import org.junit.Test; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.diagnostics.FailureAnalysis; +import org.springframework.mock.env.MockEnvironment; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.assertj.core.api.Assertions.catchThrowable; +import static org.mockito.Mockito.mock; + +/** + * Test for {@link PolarisImportExceptionFailureAnalyzer}. + * + * @author wlx + * @date 2022/7/16 4:11 下午 + */ +public class PolarisImportExceptionFailureAnalyzerTest { + + @Test + public void failureAnalyzerTest() { + SpringApplication app = mock(SpringApplication.class); + MockEnvironment environment = new MockEnvironment(); + PolarisConfigDataMissingEnvironmentPostProcessor processor = new PolarisConfigDataMissingEnvironmentPostProcessor(); + assertThatThrownBy(() -> processor.postProcessEnvironment(environment, app)) + .isInstanceOf(PolarisConfigDataMissingEnvironmentPostProcessor.ImportException.class); + Throwable throwable = catchThrowable(() -> processor.postProcessEnvironment(environment, app)); + PolarisImportExceptionFailureAnalyzer failureAnalyzer = new PolarisImportExceptionFailureAnalyzer(); + FailureAnalysis analyze = failureAnalyzer.analyze(throwable); + assertThat(StringUtils.isNotBlank(analyze.getAction())).isTrue(); + } +}