Despliegue
Ejecutándose como una aplicación independiente
IPF Operational Dashboard puede ser creado con 2 perfiles de maven:
-
contenedor- Genera contenedores de docker
-
runnable- Genera un archivo jar ejecutable para funcionar como una aplicación independiente.
En este caso, estamos interesados en el archivo jar ejecutable.
Al construir IPF Operational Dashboard utilizando el arquetipo, tanto el container como el runnable pueden ser generados en el pom.xml.
Si desea generar el runnable, deberá invocar el perfil runnable de la siguiente manera:
mvn clean install -P runnable
Todos los archivos JAR ejecutables de IPF se producen como Spring Boot aplicaciones. Para ejecutar un IPF Operational Dashboard, usted debe ejecutar lo siguiente:
java -cp ipf-operational-dashboard-docker/target/com.iconsolutions.payments_ipf-operational-dashboard-docker_<version>-runnable.jar:config -Dconfig.override_with_env_vars=true -Dloader.main=com.iconsolutions.ipf.gui. BusinessOperationsMain org.springframework.boot.loader.launch. PropertiesLauncher
Reemplace el `<version>` placeholder en el comando con su IPF específico Operational Dashboard construir la versión antes de la ejecución. Por ejemplo, si su versión de compilación es |
Si utiliza Windows, necesitamos reemplazar el primer ":" con un ";", a saber: "com.iconsolutions.payments_ipf-operational-dashboard-docker_<version>-runnable.jar;config" |
Si usted está sobrescribiendo alguna de la configuración predeterminada para las aplicaciones, entonces, en este ejemplo, el archivo de configuración para la aplicación,application.conf, viviría en la carpeta de configuración como se define en :config. Luego aprovechamos el Spring Boot_Properties Launcher_ para cargar las propiedades en la aplicación.
Información adicional
Para empaquetar el javacript requerido para los módulos IPF que ha elegido servir para su IPF Operational Dashboard necesitará estas dos secciones de código en el pom de su aplicación web:
<build>
<resources>
<resource>
<directory>${project.build.directory}/static</directory>
<targetPath>static</targetPath>
</resource>
</resources>
</build>
<build>
<plugins>
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<version>1.12.0</version>
<configuration>
<nodeVersion>v20.11.1</nodeVersion>
<npmVersion>10.2.4</npmVersion>
<installDirectory>${project.build.directory}</installDirectory>
</configuration>
<executions>
<execution>
<id>install node and npm</id>
<goals>
<goal>install-node-and-npm</goal>
</goals>
</execution>
<execution>
<id>Build</id>
<goals>
<goal>npm</goal>
</goals>
<configuration>
<arguments>run build</arguments>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Deberá coincidir esto en su pom de servicio con las dependencias de java requeridas, ops-gui-service-ng-starter, su aplicación web, commons-codec y los módulos de IPF que elija:
<dependencies>
<dependency>
<groupId>com.iconsolutions.ipf.gui</groupId>
<artifactId>ops-gui-service-ng-starter</artifactId>
</dependency>
<dependency>
<groupId>com.iconsolutions.payments</groupId>
<artifactId>iconsolutions</artifactId>
</dependency>
<dependency>
<groupId>com.iconsolutions.ipf.gui</groupId>
<artifactId>ops-gui-service-ng-cluster</artifactId>
</dependency>
<dependency>
<groupId>com.iconsolutions.ipf.gui</groupId>
<artifactId>ops-gui-service-ng-htm</artifactId>
</dependency>
<dependency>
<groupId>com.iconsolutions.ipf.gui</groupId>
<artifactId>ops-gui-service-ng-metrics</artifactId>
</dependency>
<dependency>
<groupId>com.iconsolutions.ipf.gui</groupId>
<artifactId>ops-gui-service-ng-ods</artifactId>
</dependency>
<dependency>
<groupId>com.iconsolutions.ipf.gui</groupId>
<artifactId>ops-gui-service-ng-processing-settings</artifactId>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</dependency>
</dependencies>
Para crear el archivo jar ejecutable requerido.
Construcción como Contenedor
Todas las aplicaciones que IPF produce se envían a ipf-lanzamientos en Nexus. Los archivos jar ejecutables estarán disponibles como un artefacto con un sufijo de runnable en el repositorio de Nexus para cada versión de la aplicación que necesite. Por ejemplo, si desea obtener la IPF Operational Dashboard el archivo jar ejecutable para la versión 8.7.1 lo encontrará en este enlace:
El siguiente Dockerfile puede ser utilizado como una plantilla para la integración con su propio contenedor base subyacente.
FROM registry.ipf.iconsolutions.com/ubi8-minimal-openjdk-17:latest
USER root
RUN mkdir -p /ipf-operational-dashboard-service/conf /ipf-operational-dashboard-service/lib
COPY ipf-operational-dashboard-docker-<ipf-dashboard-version>-runnable.jar /ipf-operational-dashboard-service/lib/
COPY cinnamon-agent-<cinnamon-version>.jar /ipf-operational-dashboard-service/lib/
WORKDIR /ipf-operational-dashboard-service
EXPOSE 8080
HEALTHCHECK --interval=30s --timeout=3s --retries=1 CMD wget -qO- http://localhost:8080/actuator/health/ | grep UP || exit 1
ENTRYPOINT java \
-javaagent:/ipf-operational-dashboard-service/lib/cinnamon-agent-<cinnamon-version>.jar \
-cp "/ipf-operational-dashboard-service/lib/ipf-operational-dashboard-docker-<ipf-dashboard-version>-runnable.jar:/ipf-operational-dashboard-service/conf" \
$IPF_OPS_GUI_SERVICE_JAVA_ARGS \
-Dconfig.override_with_env_vars=true \
-Dloader.main=com.iconsolutions.ipf.gui.BusinessOperationsMain \
org.springframework.boot.loader.launch.PropertiesLauncher
Al construir el Dockerfile, asegúrese de:
Ambos valores deben ser especificados con precisión para garantizar un despliegue y compatibilidad adecuados. |
Kubernetes y OpenShift
El IPF Operational Dashboard opera como una aplicación sin estado y no agrupada, por lo que puede ser fácilmente desplegada utilizando los siguientes manifiestos.
Manifiesto de Despliegue
apiVersion: apps/v1
kind: Deployment
metadata:
name: ipf-operational-dashboard
labels:
app: operational-dashboard
product: ipfv2
spec:
replicas: 3
selector:
matchLabels:
app: operational-dashboard
product: ipfv2
template:
metadata:
labels:
app: operational-dashboard
product: ipfv2
spec:
containers:
- name: operational-dashboard
image: CONTAINER_REGISTRY/ipf-operational-dashboard-service:VERSION
imagePullPolicy: Always
ports:
- containerPort: 8080
name: server-port
- containerPort: 55001
name: akka-artery
env:
- name: IPF_PODNAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: "AKKA_CLUSTER_BOOTSTRAP_SERVICE_NAME"
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.labels['app']
- name: IPF_JAVA_ARGS
value: "-XX:+UseContainerSupport -XX:MaxRAMPercentage=60 -XX:InitialRAMPercentage=60 -XX:-PreferContainerQuotaForCPUCount"
resources:
limits:
memory: 3.5Gi
requests:
memory: 2Gi
cpu: 500M
livenessProbe:
httpGet:
path: /actuator/health
port: server-port
scheme: HTTP
initialDelaySeconds: 60
periodSeconds: 5
timeoutSeconds: 1
failureThreshold: 3
successThreshold: 1
readinessProbe:
httpGet:
path: /actuator/health
port: server-port
scheme: HTTP
initialDelaySeconds: 60
periodSeconds: 5
timeoutSeconds: 1
failureThreshold: 3
successThreshold: 1
startupProbe:
httpGet:
path: /actuator/health
port: server-port
scheme: HTTP
periodSeconds: 10
failureThreshold: 30
volumeMounts:
- name: configuration-dashboard
mountPath: /operational-dashboard-service/conf
volumes:
- name: configuration-dashboard
projected:
defaultMode: 420
sources:
- secret:
name: operational-dashboard
items:
- key: users.conf
mode: 420
path: users.conf
- configMap:
name: operational-dashboard-cm
items:
- key: logback.xml
mode: 420
path: logback.xml
- key: application.conf
mode: 420
path: application.conf
- configMap:
name: operational-dashboard-cm-summary-layout
items:
- key: summary-layout.conf
mode: 420
path: summary-layout.conf
- configMap:
name: ipf-operational-dashboard-cm-reason-codes
items:
- key: reason-codes.conf
mode: 420
path: reason-codes.conf
Manifiesto de Servicio
apiVersion: v1
kind: Service
metadata:
name: operational-dashboard
labels:
app: operational-dashboard
product: ipfv2
spec:
selector:
app: operational-dashboard
product: ipfv2
ports:
- name: server-port
protocol: TCP
port: 8080
targetPort: 8080
Manifiesto de ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: ipf-operational-dashboard-cm
data:
application.conf: |
spring.data.mongodb.uri = "${ipf.mongodb.url}"
ipf {
business-operations = {
auth = {
jwt {
secret = ""
roles-claim = "roles"
}
cors {
allowed-origin-patterns = [ "*" ]
}
saml2 {
enabled = true
verification-certificate = "classpath:idp.crt"
registration-id = "sample-client"
single-sign-on-service-location = "https://simplesaml.${environment_name}.ipfdev.co.uk/simplesaml/saml2/idp/SSOService.php"
single-log-out-service-location = "https://simplesaml.${environment_name}.example.org/simplesaml/saml2/idp/SingleLogoutService.php"
identity-provider-entity-id = "https://simplesaml.${environment_name}.example.org/simplesaml/saml2/idp/metadata.php"
service-provider-entity-id = "sample-client"
want-authn-requests-signed = false
uid-attribute = "uid"
roles-attribute = "roles"
roles-separator = ","
return-url = "/"
}
oauth2 {
enabled = true
registrationId = "keycloak"
clientId = "login-app"
clientSecret = "802e7940-648b-4925-8079-24fa6dc47afe"
scopes = "openid, roles"
authorizationUri = "https://keycloak.${environment_name}.example.org/realms/demo/protocol/openid-connect/auth"
tokenUri = "https://keycloak.${environment_name}.example.org/realms/demo/protocol/openid-connect/token"
jwkSetUri = "https://keycloak.${environment_name}.example.org/realms/demo/protocol/openid-connect/certs"
returnUrl = "/"
rolesFromAttributes = true
rolesAttribute = "roles"
username = "preferred_username"
}
}
audit = {
enabled = true
}
cluster-management = {
systems = [
{
name = "Payments Service"
base-urls = [
"http://payment-service:8558"
],
akka-management = true,
actuator = {
protocol = "http",
port = "8080"
}
},
{
name = "Notification Service"
base-urls = [
"http://notification-service:8558"
],
akka-management = true,
actuator = {
protocol = "http",
port = "8080"
}
},
{
name = "ODS Ingestion"
base-urls = [
"http://ods-ingestion:8558"
],
akka-management = true,
actuator = {
protocol = "http",
port = "8080"
}
},
{
name = "ODS Inquiry"
base-urls = [
"http://ods-inquiry:8080"
],
akka-management = false,
actuator = {
protocol = "http",
port = "8080"
}
}
]
}
metrics = {
http = {
client = {
host = "grafana"
port = "3000"
endpoint-url = "/api/health"
}
}
metric-url = "http://grafana:3000",
local-metric-url = "https://grafana.${environment_name}.example.org",
call-timeout = 30s,
dashboards = [
{
title: "Business Metrics",
name: "transactions",
id: "0000000001",
panels: [
{id: "1"},
{id: "2"},
{id: "15"},
{id: "16&var-lookback_period=1y"}
],
columns: "2"
},
{
title: "Debtor Credit Transfer Metrics",
name: "transactions",
id: "0000000001",
panels: [
{id: "4&var-behaviour=DebtorCreditTransferBehaviour&var-latency_type=FULL_FLOW", colspan: "1"},
{id: "4&var-behaviour=DebtorCreditTransferBehaviour&var-latency_type=CSM_STATES_ONLY", colspan: "1"},
{id: "4&var-behaviour=DebtorCreditTransferBehaviour&var-latency_type=NO_CSM_STATES", colspan: "1"},
{id: "8&var-behaviour=DebtorCreditTransferBehaviour", colspan: "2"}
],
columns: "3"
},
{
title: "Creditor Credit Transfer Metrics",
name: "transactions",
id: "0000000001",
panels: [
{id: "4&var-behaviour=CreditorCreditTransferBehaviour&var-latency_type=FULL_FLOW", colspan: "1"},
{id: "4&var-behaviour=CreditorCreditTransferBehaviour&var-latency_type=CSM_STATES_ONLY", colspan: "1"},
{id: "4&var-behaviour=CreditorCreditTransferBehaviour&var-latency_type=NO_CSM_STATES", colspan: "1"},
{id: "8&var-behaviour=CreditorCreditTransferBehaviour", colspan: "2"}
],
columns: "3"
},
{
title: "Connector Metrics",
name: "ipf-connectors",
id: "0000000002",
panels: [
{id: "1"},
{id: "2"},
{id: "4", colspan: "2"},
{id: "5", colspan: "2"}
],
columns: "2"
}
]
}
payment-search = {
ods = {
security = {
enabled = false
grant_type = "password"
client_id = "login-app"
client_secret = "802e7940-648b-4925-8079-24fa6dc47afe"
username = "test"
password = "p4ssw0rd"
jwt-certificate = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhXrGmY331co1PX/tDGdMpChoaVfokUMxdrrRul4lLIGSOAEBRegLdmmmY7FgCSTtIhmkkwZWu3gaZLs5+oyld9ncXSL4OpQQvoCOd84RvWiHLhxPBynuYmypTQUP2kLeM3ntCsXI13SwN59tE/y4H/GVGTBDrfN2ELaS43OeZRpQuW1XqLWuyNGDCtC4V7cd+gld5uDBa93PUB40ypWqnYQVrC+PRiiiXcF6uyEgkOgMinR8LerKFi/iFpuMytJa9zW0d/O5aOceulWDjUJeqf+6EbonWjfJv5GMSKdsCjQ6rnq/a1gaxSyYeCctmqtUpu0Ogjjjwfwf3qkj6fWUawIDAQAB"
}
}
ods-inquiry-url = "http://ods-inquiry:8080"
payment-summaries.http.client.endpoint-url = ${ipf.business-operations.payment-search.ods-inquiry-url}"/views/summaries/payments"
payment-details.http.client.endpoint-url = ${ipf.business-operations.payment-search.ods-inquiry-url}"/views/details"
system-events.http.client.endpoint-url = ${ipf.business-operations.payment-search.ods-inquiry-url}"/catalogue/process-objects/system-events"
message-logs.http.client.endpoint-url = ${ipf.business-operations.payment-search.ods-inquiry-url}"/catalogue/process-objects/message-logs"
process-flow-events.http.client.endpoint-url = ${ipf.business-operations.payment-search.ods-inquiry-url}"/catalogue/process-objects/process-flow-events"
payment-objects.http.client.endpoint-url = ${ipf.business-operations.payment-search.ods-inquiry-url}"/all/payment-objects"
custom-objects.http.client.endpoint-url = ${ipf.business-operations.payment-search.ods-inquiry-url}"/all/custom-objects"
auth-server.http.client.endpoint-url = ${ipf.business-operations.payment-search.ods-inquiry-url}"/realms/demo/protocol/openid-connect/token"
}
}
}
logback.xml: |
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<target>System.out</target>
<encoder>
<pattern>[%date{ISO8601}] [%level] [%logger] [%marker] [%thread] - %msg%n</pattern>
</encoder>
</appender>
<appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
<queueSize>8192</queueSize>
<neverBlock>true</neverBlock>
<appender-ref ref="CONSOLE" />
</appender>
<logger name="com.iconsolutions" level="ERROR"/>
<root level="INFO">
<appender-ref ref="ASYNC"/>
</root>
</configuration>