Skip to content

Commit d0400b9

Browse files
committed
Add Nacos Config Server integration and tests
Introduces NacosConfigServerAutoConfiguration and NacosEnvironmentRepository to support Nacos as a backend for Spring Cloud Config Server. Updates dependencies in pom.xml, registers auto-configuration, and adds integration tests using Testcontainers with a Docker Compose setup for Nacos.
1 parent 41beb6e commit d0400b9

6 files changed

Lines changed: 277 additions & 0 deletions

File tree

microsphere-spring-cloud-gateway-commons/pom.xml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,13 +69,27 @@
6969
<optional>true</optional>
7070
</dependency>
7171

72+
<!-- Spring Cloud Config Server -->
73+
<dependency>
74+
<groupId>org.springframework.cloud</groupId>
75+
<artifactId>spring-cloud-config-server</artifactId>
76+
<optional>true</optional>
77+
</dependency>
78+
7279
<!-- Spring -->
7380
<dependency>
7481
<groupId>org.springframework</groupId>
7582
<artifactId>spring-web</artifactId>
7683
<optional>true</optional>
7784
</dependency>
7885

86+
<!-- Spring Cloud Alibaba Nacos Config -->
87+
<dependency>
88+
<groupId>com.alibaba.cloud</groupId>
89+
<artifactId>spring-alibaba-nacos-config</artifactId>
90+
<optional>true</optional>
91+
</dependency>
92+
7993
<!-- Testing -->
8094
<dependency>
8195
<groupId>org.springframework.boot</groupId>
@@ -90,6 +104,19 @@
90104
<scope>test</scope>
91105
</dependency>
92106

107+
<!-- Testcontainers -->
108+
<dependency>
109+
<groupId>org.testcontainers</groupId>
110+
<artifactId>testcontainers-junit-jupiter</artifactId>
111+
<scope>test</scope>
112+
<exclusions>
113+
<exclusion>
114+
<groupId>junit</groupId>
115+
<artifactId>junit</artifactId>
116+
</exclusion>
117+
</exclusions>
118+
</dependency>
119+
93120
<!-- Hibernate Validator -->
94121
<dependency>
95122
<groupId>org.hibernate.validator</groupId>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package io.microsphere.spring.cloud.gateway.commons.config.server.nacos.autoconfigure;
19+
20+
21+
import com.alibaba.cloud.nacos.NacosConfigAutoConfiguration;
22+
import com.alibaba.cloud.nacos.NacosConfigEnabledCondition;
23+
import com.alibaba.cloud.nacos.NacosConfigManager;
24+
import com.alibaba.cloud.nacos.NacosConfigProperties;
25+
import io.microsphere.spring.cloud.gateway.commons.config.server.nacos.environment.NacosEnvironmentRepository;
26+
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
27+
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
28+
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
29+
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
30+
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
31+
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
32+
import org.springframework.cloud.config.server.EnableConfigServer;
33+
import org.springframework.cloud.config.server.config.ConfigServerAutoConfiguration;
34+
import org.springframework.context.annotation.Bean;
35+
import org.springframework.context.annotation.Conditional;
36+
import org.springframework.context.annotation.Configuration;
37+
38+
import static org.springframework.cloud.config.server.config.ConfigServerProperties.PREFIX;
39+
40+
/**
41+
* Nacos Config Server Auto-Configuration.
42+
*
43+
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
44+
* @since 1.0.0
45+
*/
46+
@ConditionalOnClass(EnableConfigServer.class) // If class of @EnableConfigServer is present in class-path
47+
@ConditionalOnProperty(prefix = PREFIX, name = "enabled", matchIfMissing = true)
48+
@Conditional(NacosConfigEnabledCondition.class)
49+
@AutoConfigureBefore(ConfigServerAutoConfiguration.class)
50+
@AutoConfigureAfter(NacosConfigAutoConfiguration.class)
51+
@Configuration(proxyBeanMethods = false)
52+
public class NacosConfigServerAutoConfiguration {
53+
54+
@Bean
55+
@ConditionalOnMissingBean
56+
@ConditionalOnBean(value = {NacosConfigManager.class, NacosConfigProperties.class})
57+
public NacosEnvironmentRepository nacosEnvironmentRepository(NacosConfigManager nacosConfigManager,
58+
NacosConfigProperties nacosConfigProperties) {
59+
return new NacosEnvironmentRepository(nacosConfigManager, nacosConfigProperties);
60+
}
61+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package io.microsphere.spring.cloud.gateway.commons.config.server.nacos.environment;
19+
20+
21+
import com.alibaba.cloud.nacos.NacosConfigManager;
22+
import com.alibaba.cloud.nacos.NacosConfigProperties;
23+
import com.alibaba.nacos.api.config.ConfigService;
24+
import org.springframework.cloud.config.environment.Environment;
25+
import org.springframework.cloud.config.environment.PropertySource;
26+
import org.springframework.cloud.config.server.environment.EnvironmentRepository;
27+
import org.springframework.util.StringUtils;
28+
29+
import java.io.IOException;
30+
import java.io.StringReader;
31+
import java.util.Properties;
32+
33+
import static com.alibaba.nacos.api.common.Constants.DEFAULT_GROUP;
34+
import static io.microsphere.lang.function.ThrowableSupplier.execute;
35+
import static java.lang.String.format;
36+
37+
/**
38+
* Nacos {@link EnvironmentRepository}.
39+
*
40+
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
41+
* @since 0.2.0
42+
*/
43+
public class NacosEnvironmentRepository implements EnvironmentRepository {
44+
45+
private final NacosConfigProperties nacosConfigProperties;
46+
47+
private final ConfigService configService;
48+
49+
public NacosEnvironmentRepository(NacosConfigManager nacosConfigManager, NacosConfigProperties nacosConfigProperties) {
50+
this.nacosConfigProperties = nacosConfigProperties;
51+
this.configService = nacosConfigManager.getConfigService();
52+
}
53+
54+
@Override
55+
public Environment findOne(String application, String profile, String label) {
56+
57+
String dataId = application + "-" + profile + ".properties";
58+
59+
String configContent = execute(() -> configService.getConfig(dataId, DEFAULT_GROUP, this.nacosConfigProperties.getTimeout()));
60+
61+
return createEnvironment(configContent, application, profile);
62+
}
63+
64+
private Environment createEnvironment(String configContent, String application,
65+
String profile) {
66+
67+
Environment environment = new Environment(application, profile);
68+
69+
Properties properties = createProperties(configContent);
70+
71+
String propertySourceName = format("Nacos[application : %s , profile : %s]", application, profile);
72+
73+
PropertySource propertySource = new PropertySource(propertySourceName,
74+
properties);
75+
76+
environment.add(propertySource);
77+
78+
return environment;
79+
}
80+
81+
private Properties createProperties(String configContent) {
82+
Properties properties = new Properties();
83+
if (StringUtils.hasText(configContent)) {
84+
try {
85+
properties.load(new StringReader(configContent));
86+
} catch (IOException e) {
87+
throw new IllegalStateException("The format of content is a properties");
88+
}
89+
}
90+
return properties;
91+
}
92+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
io.microsphere.spring.cloud.gateway.commons.config.server.nacos.autoconfigure.NacosConfigServerAutoConfiguration
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package io.microsphere.spring.cloud.gateway.commons.config.server.nacos.autoconfigure;
19+
20+
21+
import org.junit.jupiter.api.AfterAll;
22+
import org.junit.jupiter.api.BeforeAll;
23+
import org.junit.jupiter.api.Test;
24+
import org.junit.jupiter.api.condition.EnabledIfSystemProperty;
25+
import org.junit.jupiter.api.extension.ExtendWith;
26+
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
27+
import org.springframework.test.context.ContextConfiguration;
28+
import org.springframework.test.context.TestPropertySource;
29+
import org.springframework.test.context.junit.jupiter.SpringExtension;
30+
import org.testcontainers.containers.ComposeContainer;
31+
import org.testcontainers.junit.jupiter.EnabledIfDockerAvailable;
32+
33+
import java.io.File;
34+
import java.net.URL;
35+
36+
import static org.testcontainers.containers.wait.strategy.Wait.forLogMessage;
37+
38+
/**
39+
* {@link NacosConfigServerAutoConfiguration} Integration Test
40+
*
41+
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
42+
* @see NacosConfigServerAutoConfiguration
43+
* @since 1.0.0
44+
*/
45+
@EnabledIfSystemProperty(named = "testcontainers.enabled", matches = "true")
46+
@EnabledIfDockerAvailable
47+
@ExtendWith(SpringExtension.class)
48+
@ContextConfiguration(classes = {
49+
NacosConfigServerAutoConfigurationIntegrationTest.class
50+
})
51+
@TestPropertySource(properties = {
52+
"spring.application.name=test",
53+
})
54+
@EnableAutoConfiguration
55+
class NacosConfigServerAutoConfigurationIntegrationTest {
56+
57+
private static ComposeContainer composeContainer;
58+
59+
@BeforeAll
60+
static void beforeAll() throws Exception {
61+
ClassLoader classLoader = NacosConfigServerAutoConfigurationIntegrationTest.class.getClassLoader();
62+
URL resource = classLoader.getResource("META-INF/docker/service-registry-servers.yml");
63+
File dockerComposeFile = new File(resource.toURI());
64+
composeContainer = new ComposeContainer(dockerComposeFile);
65+
composeContainer.waitingFor("nacos", forLogMessage(".*Nacos started successfully.*", 1))
66+
.start();
67+
}
68+
69+
@AfterAll
70+
static void afterAll() {
71+
composeContainer.stop();
72+
}
73+
74+
@Test
75+
void test() {
76+
77+
}
78+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
services:
2+
# zookeeper:
3+
# image: zookeeper
4+
# restart: always
5+
# ports:
6+
# - "2181:2181"
7+
#
8+
# consul:
9+
# image: hashicorp/consul
10+
# ports:
11+
# - "8500:8500"
12+
13+
nacos:
14+
image: nacos/nacos-server:v3.1.1
15+
ports:
16+
- "8848:8848"
17+
environment:
18+
- MODE=standalone

0 commit comments

Comments
 (0)