From 244b1b480e6c365530e8a8c8b414f8e7a7b90d88 Mon Sep 17 00:00:00 2001
From: OZGCloud <ozgcloud@mgm-tp.com>
Date: Wed, 24 Jan 2024 17:49:43 +0100
Subject: [PATCH] OZG-4814 Makes administration to a spring cloud config server
 on an mongodb

---
 pom.xml                                       |  5 ++
 .../admin/AdministrationApplication.java      |  3 +
 .../environment/EnableMongoConfigServer.java  | 21 +++++
 .../MongoEnvironmentRepository.java           | 49 +++++++++++
 ...ngoEnvironmentRepositoryConfiguration.java | 20 +++++
 .../environment/MongoPropertySource.java      | 15 ++++
 src/main/resources/application.yml            |  6 ++
 .../environment/MongoConfigServerTest.java    | 30 +++++++
 .../MongoEnvironmentRepositoryTest.java       | 84 +++++++++++++++++++
 9 files changed, 233 insertions(+)
 create mode 100644 src/main/java/de/ozgcloud/admin/environment/EnableMongoConfigServer.java
 create mode 100644 src/main/java/de/ozgcloud/admin/environment/MongoEnvironmentRepository.java
 create mode 100644 src/main/java/de/ozgcloud/admin/environment/MongoEnvironmentRepositoryConfiguration.java
 create mode 100644 src/main/java/de/ozgcloud/admin/environment/MongoPropertySource.java
 create mode 100644 src/main/resources/application.yml
 create mode 100644 src/test/java/de/ozgcloud/admin/environment/MongoConfigServerTest.java
 create mode 100644 src/test/java/de/ozgcloud/admin/environment/MongoEnvironmentRepositoryTest.java

diff --git a/pom.xml b/pom.xml
index 2b0b19fe..ea3f1506 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 36c0f359..a0c579e4 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 00000000..b1f96d31
--- /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 00000000..e3a38c3a
--- /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 00000000..7be2d7e5
--- /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 00000000..17abbf66
--- /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 00000000..9ddc559f
--- /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 00000000..2860591f
--- /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 00000000..6de5e495
--- /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());
+	}
+}
-- 
GitLab