Hace relativamente poco tiempo, me encontré con la necesidad de dockerizar una api y ponerla en el cloud de amazon.
Después de la «dockerización», llego la generación de diferentes entornos y stacks de propiedades repetidas en las diferentes api y módulos que teníamos en ese momento. Y entonces.. aquí estamos, explicando como poner nuestras propiedades en un repositorio y consumirlas para tenerlas centralizadas y versionadas.
Realmente, en el caso que comenté., al final se utilizó «parameter store«, pero yo hice un pequeño MVP, que os voy a mostrar ahora mismo.
Tabla de contenidos
Versionando nuestra configuración
Lo primero que hice para montar este MVP, es subir unas propiedades a un repositorio, publico. Bien se puede reproducir en uno privado, especificando las credenciales o usando claves de acceso seguras. En este caso, sólo quería validar hipótesis, partiendo desde una configuración básica.
GITHUB properties: https://github.com/apascualco/spring-cloud-properties
Levantando nuestro propio servidor de configuraciones
GITHUB servidor: https://github.com/apascualco/spring-cloud-config-server
Las dependencias pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.apascualco</groupId>
<artifactId>spring-cloud-config-server</artifactId>
<version>1.0-SNAPSHOT</version>
<name>Config Server</name>
<description>Spring cloud configuration server</description>
<properties>
<java-version>1.8</java-version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring-cloud.version>2.2.2.RELEASE</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
<version>${spring-cloud.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>${spring-cloud.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.2.2.RELEASE</version>
</plugin>
<plugin>
<groupId>com.google.cloud.tools</groupId>
<artifactId>jib-maven-plugin</artifactId>
<version>1.1.2</version>
<configuration>
<to>
<image>${project.artifactId}</image>
</to>
<from>
<image>openjdk:8-jdk-alpine</image>
</from>
</configuration>
</plugin>
</plugins>
</build>
</project>
Cómo podéis ver necesitamos publicar el endpoint que consumiremos o consumira nuestro cliente y spring-cloud-config-server.
Normalmente, este tipo de ejemplo, estan cubiertos por la librería de securidad y configurados de tras de unas credenciales, pero esto lo dejo al gusto del consumidor.
El objetivo principal de esta «practica», es mostrar como funciona de la forma más básica posible y de allí, puede crecer hasta que vosotros queráis.
El plugin de google JIB, tan sólo nos facilita la parte de meter nuestro server en docker, hice un pequeño post aquí: https://www.apascualco.com/cloud/docker/generando-imagen-docker-con-maven-spring/
Las propiedades
server.port=8888
spring.cloud.config.server.git.uri=https://github.com/apascualco/spring-cloud-properties
spring.cloud.config.server.git.clone-on-start=true
Poco que decir, aquí se pondrían las credenciales de seguridad si las necesitáramos.
Qué veremos ? http://localhost:8888/hhjh/development
Cuando terminemos y sepamos más veremos dónde o que path buscar para que salga esto, ojo spoiler! http://localhost:8888/client/development
Configurando nuestro cliente
GITHUB cliente: https://github.com/apascualco/spring-cloud-config-client
Las dependencias pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.apascualco</groupId>
<artifactId>spring-cloud-config-client</artifactId>
<version>1.0-SNAPSHOT</version>
<name>Config Client</name>
<description>Spring cloud configuration client</description>
<properties>
<java-version>1.8</java-version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring-cloud.version>2.2.2.RELEASE</spring-cloud.version>
<jackson-databind.version>2.10.3</jackson-databind.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
<version>${spring-cloud.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>${spring-cloud.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<version>${spring-cloud.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson-databind.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.2.2.RELEASE</version>
</plugin>
</plugins>
</build>
</project>
Seguimos con el jib, para el cliente y obviamente el web para publicar unos rest y el startet de spring cloud config.
También he añadido la dependencia del actuator y una mandatoria en la versión de spring cloud que utilizo.
Los enpoints
package com.apascualco.client;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class PropertiesController {
@Value("${client.environment}")
private String environment;
@Value("${client.extra.name}")
private String extraProperty;
@GetMapping(value = "/env", produces = MediaType.TEXT_PLAIN_VALUE)
public String properties() {
return environment;
}
@GetMapping(value = "/extra", produces = MediaType.TEXT_PLAIN_VALUE)
public String extra() {
return extraProperty;
}
}
Para lanzar nuestro servidor, deberemos de especificar los profiles activos o bien como variable de entorno o pasando los profiles a la aplicación: spring.active.profile=development,extra.
Yo utilizaré el IDE
El resultado del cliente
Dependiendo de los profiles activo pillará una configuración u otra. Si vemos el nombre de las propiedades en nuestro repo, podemos observar:
- La primera parte «client» -> spring.application.name=client (nuestra config)
- La segunda parte development -> nombre del profile
el resultado es el de arriba. Y aquí la información que nos devuelve el actuator/env http://localhost:8080/actuator/env