diff --git a/pom.xml b/pom.xml index 2b0b19feaa77863d337c64e5568fabad88815fdf..ea3f1506da83af57a4b82d29848d9616ab719876 100644 --- a/pom.xml +++ b/pom.xml @@ -31,6 +31,11 @@ <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> + <dependency> + <groupId>org.springframework.cloud</groupId> + <artifactId>spring-cloud-config-server</artifactId> + <version>4.1.0</version> + </dependency> <!-- Dev --> <dependency> diff --git a/src/main/java/de/ozgcloud/admin/AdministrationApplication.java b/src/main/java/de/ozgcloud/admin/AdministrationApplication.java index 36c0f359fa7ffdd7c83f9f2d41c3c751c9cd15bf..a0c579e40acea317e9280c230706e1321a8a67ca 100644 --- a/src/main/java/de/ozgcloud/admin/AdministrationApplication.java +++ b/src/main/java/de/ozgcloud/admin/AdministrationApplication.java @@ -3,7 +3,10 @@ package de.ozgcloud.admin; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import de.ozgcloud.admin.environment.EnableMongoConfigServer; + @SpringBootApplication +@EnableMongoConfigServer public class AdministrationApplication { public static void main(String[] args) { diff --git a/src/main/java/de/ozgcloud/admin/environment/EnableMongoConfigServer.java b/src/main/java/de/ozgcloud/admin/environment/EnableMongoConfigServer.java new file mode 100644 index 0000000000000000000000000000000000000000..b1f96d31907f36f81758ab266da18d21a6406707 --- /dev/null +++ b/src/main/java/de/ozgcloud/admin/environment/EnableMongoConfigServer.java @@ -0,0 +1,21 @@ +package de.ozgcloud.admin.environment; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.springframework.cloud.config.server.EnableConfigServer; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; + +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Configuration +@Import(MongoEnvironmentRepositoryConfiguration.class) +@EnableConfigServer +public @interface EnableMongoConfigServer { + +} diff --git a/src/main/java/de/ozgcloud/admin/environment/MongoEnvironmentRepository.java b/src/main/java/de/ozgcloud/admin/environment/MongoEnvironmentRepository.java new file mode 100644 index 0000000000000000000000000000000000000000..e3a38c3ac548e258d39b1a74439516e14c13c246 --- /dev/null +++ b/src/main/java/de/ozgcloud/admin/environment/MongoEnvironmentRepository.java @@ -0,0 +1,49 @@ +package de.ozgcloud.admin.environment; + +import java.util.List; +import java.util.stream.Collectors; + +import org.springframework.cloud.config.environment.Environment; +import org.springframework.cloud.config.environment.PropertySource; +import org.springframework.cloud.config.server.environment.EnvironmentRepository; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.query.Criteria; +import org.springframework.data.mongodb.core.query.Query; + +public class MongoEnvironmentRepository implements EnvironmentRepository { + private static final String LABEL = "label"; + private static final String PROFILE = "profile"; + private static final String DEFAULT = "default"; + + private MongoTemplate mongoTemplate; + + public MongoEnvironmentRepository(MongoTemplate mongoTemplate) { + this.mongoTemplate = mongoTemplate; + } + + @Override + public Environment findOne(String application, String profile, String label) { + Query query = buildQuery(profile, label); + List<MongoPropertySource> sources = mongoTemplate.find(query, MongoPropertySource.class, application); + Environment environment = new Environment(application, new String[] { profile }, label == null ? DEFAULT : label, null, null); + System.out.println(label); + + environment.addAll(sources.stream().map(this::transformMonPropertySourceToPropertySource).collect(Collectors.toList())); + + return environment; + } + + private Query buildQuery(String profile, String label) { + Query query = new Query(); + query.addCriteria(Criteria.where(LABEL).in(new String[] { label, null })); + query.addCriteria(Criteria.where(PROFILE).in(new String[] { profile, null })); + return query; + } + + private PropertySource transformMonPropertySourceToPropertySource(MongoPropertySource mongoPropertySource) { + String sourceName = mongoPropertySource.getProfile() + "-" + + ((mongoPropertySource.getLabel() == null) ? DEFAULT : mongoPropertySource.getLabel()); + return new PropertySource(sourceName, mongoPropertySource.getSource()); + } + +} diff --git a/src/main/java/de/ozgcloud/admin/environment/MongoEnvironmentRepositoryConfiguration.java b/src/main/java/de/ozgcloud/admin/environment/MongoEnvironmentRepositoryConfiguration.java new file mode 100644 index 0000000000000000000000000000000000000000..7be2d7e5021b6301b4b11717b593392452028047 --- /dev/null +++ b/src/main/java/de/ozgcloud/admin/environment/MongoEnvironmentRepositoryConfiguration.java @@ -0,0 +1,20 @@ +package de.ozgcloud.admin.environment; + +import org.springframework.cloud.config.server.environment.EnvironmentRepository; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.mongodb.core.MongoTemplate; + +import lombok.AllArgsConstructor; + +@Configuration +@AllArgsConstructor +public class MongoEnvironmentRepositoryConfiguration { + private MongoTemplate mongoTemplate; + + @Bean + public EnvironmentRepository environmentRepository() { + return new MongoEnvironmentRepository(mongoTemplate); + } + +} diff --git a/src/main/java/de/ozgcloud/admin/environment/MongoPropertySource.java b/src/main/java/de/ozgcloud/admin/environment/MongoPropertySource.java new file mode 100644 index 0000000000000000000000000000000000000000..17abbf660e533a2bffe250fd24712e6d6dd9769e --- /dev/null +++ b/src/main/java/de/ozgcloud/admin/environment/MongoPropertySource.java @@ -0,0 +1,15 @@ +package de.ozgcloud.admin.environment; + +import java.util.LinkedHashMap; +import java.util.Map; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class MongoPropertySource { + private String profile; + private String label; + private Map<String, Object> source = new LinkedHashMap<>(); +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 0000000000000000000000000000000000000000..9ddc559ff354c7c66c016dbd402df3e0ad21147b --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,6 @@ +spring: + data: + mongodb: + uri: mongodb://localhost/config-db +server: + port: 8888 \ No newline at end of file diff --git a/src/test/java/de/ozgcloud/admin/environment/MongoConfigServerTest.java b/src/test/java/de/ozgcloud/admin/environment/MongoConfigServerTest.java new file mode 100644 index 0000000000000000000000000000000000000000..2860591fc2aeda4915547be7e5d5b5dac31a7e6f --- /dev/null +++ b/src/test/java/de/ozgcloud/admin/environment/MongoConfigServerTest.java @@ -0,0 +1,30 @@ +package de.ozgcloud.admin.environment; + +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.boot.test.web.server.LocalServerPort; +import org.springframework.cloud.config.environment.Environment; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; + +import de.ozgcloud.admin.AdministrationApplication; + +@SpringBootTest(classes = AdministrationApplication.class, webEnvironment = WebEnvironment.DEFINED_PORT) +class MongoConfigServerTest { + private final String APPNAME = "testapp"; + private final String PROFILE = "testprofile"; + private final String LABEL = "testlabel"; + @LocalServerPort + private int port; + + @Test + void shouldHaveHttpEndpoint() { + ResponseEntity<Environment> response = new TestRestTemplate().getForEntity("http://localhost:" + + port + "/" + APPNAME + "/" + PROFILE + "/" + LABEL, Environment.class); + assertEquals(HttpStatus.OK, response.getStatusCode()); + } +} diff --git a/src/test/java/de/ozgcloud/admin/environment/MongoEnvironmentRepositoryTest.java b/src/test/java/de/ozgcloud/admin/environment/MongoEnvironmentRepositoryTest.java new file mode 100644 index 0000000000000000000000000000000000000000..6de5e4953587358ed3a92efad624141314c54ac0 --- /dev/null +++ b/src/test/java/de/ozgcloud/admin/environment/MongoEnvironmentRepositoryTest.java @@ -0,0 +1,84 @@ +package de.ozgcloud.admin.environment; + +import static org.junit.Assert.*; + +import java.util.LinkedHashMap; +import java.util.Map; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest; +import org.springframework.cloud.config.environment.Environment; +import org.springframework.cloud.config.server.environment.EnvironmentRepository; +import org.springframework.data.mongodb.core.MongoTemplate; + +@DataMongoTest +class MongoEnvironmentRepositoryTest { + private final String APPNAME = "testapp"; + private final String PROFILE = "testprofile"; + private final String LABEL = "testlabel"; + private final String PROPERTY1 = "property1"; + private final String VALUE1 = "value1"; + private final String DEFAULT = "default"; + @Autowired + private MongoTemplate mongoTemplate; + @Autowired + private EnvironmentRepository repository; + + private MongoPropertySource mongoPropertySource; + + @BeforeEach + public void prepareExampleData() { + mongoPropertySource = new MongoPropertySource(); + Map<String, Object> properties = new LinkedHashMap<>(); + + properties.put(PROPERTY1, VALUE1); + mongoPropertySource.setSource(properties); + } + + @AfterEach + public void clearData() { + mongoTemplate.dropCollection(APPNAME); + } + + @Test + void shouldFindCorrectEnvironment() { + mongoPropertySource.setProfile(PROFILE); + mongoPropertySource.setLabel(LABEL); + mongoTemplate.save(mongoPropertySource, APPNAME); + + Environment environment = repository.findOne(APPNAME, PROFILE, LABEL); + + assertEquals(APPNAME, environment.getName()); + assertEquals(LABEL, environment.getLabel()); + assertEquals(PROFILE, environment.getProfiles()[0]); + assertEquals(1, environment.getPropertySources().size()); + assertEquals(PROFILE + "-" + LABEL, environment.getPropertySources().getLast().getName()); + assertEquals(mongoPropertySource.getSource(), environment.getPropertySources().getLast().getSource()); + } + + @Test + void shouldAlwaysFindEntriesWithoutLabel() { + mongoPropertySource.setProfile(PROFILE); + mongoTemplate.save(mongoPropertySource, APPNAME); + + Environment environment = repository.findOne(APPNAME, PROFILE, LABEL); + + assertEquals(1, environment.getPropertySources().size()); + assertEquals(PROFILE + "-" + DEFAULT, environment.getPropertySources().getLast().getName()); + } + + @Test + void shouldInterpretNullLabelAsDefaultLabel() { + mongoPropertySource.setProfile(PROFILE); + mongoTemplate.save(mongoPropertySource, APPNAME); + + Environment environment = repository.findOne(APPNAME, PROFILE, null); + + assertEquals(1, environment.getPropertySources().size()); + assertEquals(DEFAULT, environment.getLabel()); + assertEquals(PROFILE + "-" + DEFAULT, environment.getPropertySources().getLast().getName()); + } +}