RJ Tech Day

master
Alberto Trevezani 2019-11-06 22:47:14 -03:00
commit 6c46ab1f3d
77 changed files with 3899 additions and 0 deletions

312
README.md 100755
View File

@ -0,0 +1,312 @@
# sample-bpe-microprofile
A sample of the BPe responsible for generating the key and the URL of the QRCode
## General
Generating the executable jar file
`mvn clean package`
Running integration tests
`mvn clean verify`
Generating the image
`mvn clean package docker:build`
Remove the image
`mvn docker:remove`
## Running the sample
**bpe-api**
`mvn thorntail:run -Dthorntail.jvmArguments=-Dbpechave.api.url=http://localhost:8280,-Dbpeqrcode.api.url=http://localhost:8180`
Debugging
`mvn thorntail:run -Dthorntail.debug.port=5006 -Dthorntail.jvmArguments=-Dbpechave.api.url=http://localhost:8280,-Dbpeqrcode.api.url=http://localhost:8180`
**bpe-qrcode**
`mvn thorntail:run -Dthorntail.jvmArguments=-Dbpechave.api.url=http://localhost:8280 -Dswarm.port.offset=100`
**bpe-chave**
`mvn thorntail:run -Dswarm.port.offset=200`
or
```
mvn clean package -f bpe-api/pom.xml docker:build
mvn clean package -f bpe-qrcode/pom.xml docker:build
mvn clean package -f bpe-chave/pom.xml docker:build
```
Inside the extra/test
```
docker-compose up --build
```
**Jaeger Traicing**
[http://localhost:16686/](http://localhost:16686/)
**Kibana**
[http://localhost:5601/](http://localhost:5601/)
**Testing the API**
QRCode
```
curl -H "Content-Type: application/json" -X POST -d '{"ambiente": "2", "uf": "23", "emissao": "20190621","documento": "68830611000","modelo": "63","serie": "001","tipoEmissao": "1","numeroDocumentoFiscal": "13"}' http://localhost:8080/api/qrcode
```
Chave
```
curl -H "Content-Type: application/json" -X POST -d '{"uf": "23", "emissao": "20190621","documento": "68830611000","modelo": "63","serie": "001","tipoEmissao": "1","numeroDocumentoFiscal": "13"}' http://localhost:8080/api/chave
```
## Kubernates
**Docker Registry**
`mkdir -p /opt/docker/auth`
`docker run --rm --entrypoint htpasswd registry:2 -Bbn admin admin > /opt/docker/auth/htpasswd`
`docker run -d -p 5000:5000 --restart=always --name registry -e REGISTRY_STORAGE_DELETE_ENABLED=true -v /opt/docker/auth:/auth -e "REGISTRY_AUTH=htpasswd" -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd -e REGISTRY_HTTP_ADDR=0.0.0.0:5000 registry:2`
**Images**
Generating the image and push them
```
mvn -Ddocker.registry=localhost:5000 -Ddocker.username=admin -Ddocker.password=admin clean package -f bpe-api/pom.xml docker:build docker:push -Pistio
mvn -Ddocker.registry=localhost:5000 -Ddocker.username=admin -Ddocker.password=admin clean package -f bpe-qrcode/pom.xml docker:build docker:push -Pistio
mvn -Ddocker.registry=localhost:5000 -Ddocker.username=admin -Ddocker.password=admin clean package -f bpe-chave/pom.xml docker:build docker:push -Pistio
```
**Registry UI**
Viewer for the images present in the Registry
[https://github.com/jc21/docker-registry-ui](https://github.com/jc21/docker-registry-ui)
```
docker run --rm -it -p 5001:80 --name registry-ui -e REGISTRY_HOST=$(ipconfig getifaddr en0):5000 -e REGISTRY_STORAGE_DELETE_ENABLED=true -e REGISTRY_SSL=false -e REGISTRY_USER=admin -e REGISTRY_PASS=admin jc21/registry-ui
```
**Minikube/Istio**
Starting the Minikube
```
minikube start --memory=8192 --cpus=4 --vm-driver=hyperkit --kubernetes-version=v1.14.0 --disk-size=30GB --insecure-registry='0.0.0.0/0'
minikube addons list
minikube addons enable heapster
minikube addons enable metrics-server
minikube addons enable ingress
```
Installing the Istio
```
# Istio 1.2.25
curl -L https://git.io/getLatestIstio | ISTIO_VERSION=1.2.25 sh -
cd istio-1.2.25
export PATH=$PWD/bin:$PATH
# install
for i in install/kubernetes/helm/istio-init/files/crd*yaml; do kubectl apply -f $i; done
kubectl apply -f install/kubernetes/istio-demo.yaml
# uninstall
kubectl delete -f install/kubernetes/istio-demo.yaml
for i in install/kubernetes/helm/istio-init/files/crd*yaml; do kubectl delete -f $i; done
```
Showing the pods
```
kubectl get pod -n istio-system
kubectl get svc -n istio-system
kubectl --namespace istio-system top pods --containers
istioctl proxy-status
```
Showing the Istio Address
```
echo "Istio Services: $(minikube ip):$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].nodePort}')"
```
Showing the IP on MAC OS
`echo "Local IP: $(ipconfig getifaddr en0)"`
**Deploying the Sample**
Creating a namespace and defining the automatic inject for the Istio
```
kubectl create -f extra/kubernates/plataform/namespace-bpe.json
kubectl label namespace bpe istio-injection=enabled --overwrite
```
Creating an environment variable for dynamic action inside the sample
```
kubectl create configmap bpe-config --from-literal='ambiente=2' -n bpe
kubectl edit configmap bpe-config -n bpe
kubectl patch deployment bpe-api-1.0.8 -p {\"spec\":{\"template\":{\"metadata\":{\"labels\":{\"date\":\"`date +'%s'`\"}}}}}" -n bpe
```
Defining the user and password to interact with the Registry
```
kubectl create secret docker-registry service-registry --namespace=bpe --docker-server=$(ipconfig getifaddr en0):5000 --docker-username=admin --docker-password=admin
```
Creating the Service, Deployment and Gateway
```
kubectl create -f extra/kubernates/plataform/bpeapi-service.yml
kubectl create -f extra/kubernates/plataform/bpeapi-deployment.yml
kubectl create -f extra/kubernates/plataform/bpeqrcode-service.yml
kubectl create -f extra/kubernates/plataform/bpeqrcode-deployment.yml
kubectl create -f extra/kubernates/plataform/bpechave-service.yml
kubectl create -f extra/kubernates/plataform/bpechave-deployment.yml
kubectl create -f extra/kubernates/networking/bpeapi-gateway.yml
```
Testing the Gateway
```
curl $(minikube ip):$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].nodePort}')/api/versao
```
Showing the pods
`kubectl get pods --namespace=bpe`
Showing the details
`kubectl describe pod bpe-api-<version> --namespace=bpe`
Testing the pod
```
kubectl exec -it $(kubectl get pod -l app=bpe-api -n bpe -o jsonpath='{.items[0].metadata.name}') -n bpe -c bpe-api -- curl bpe-api:8080/health
```
**Istio Tools**
Jaeger
```kubectl -n istio-system port-forward $(kubectl -n istio-system get pod -l app=jaeger -o jsonpath='{.items[0].metadata.name}') 15032:16686```
[http://localhost:15032](http://localhost:15032)
Kiali
```kubectl port-forward $(kubectl get pod -n istio-system -l app=kiali -o jsonpath='{.items[0].metadata.name}') -n istio-system 20001```
[http://localhost:20001/](http://localhost:20001/)
admin:admin
Grafana
```kubectl -n istio-system port-forward $(kubectl -n istio-system get pod -l app=grafana -o jsonpath='{.items[0].metadata.name}') 3000```
[http://localhost:3000/dashboard/db/istio-mesh-dashboard](http://localhost:3000/dashboard/db/istio-mesh-dashboard)
Remove port forward
```killall kubectl```
**EFK (Monitoring)**
Deploying the components
```
kubectl create namespace logging
kubectl create -f extra/kubernetes/telemetry/elastic.yaml -n logging
kubectl create -f extra/kubernetes/telemetry/kibana.yaml -n logging
kubectl create -f extra/kubernetes/telemetry/fluentd-rbac.yaml
kubectl create -f extra/kubernetes/telemetry/fluentd-daemonset.yaml
```
Showing the pods
```
kubectl get pods,service -n logging
kubectl get pods -n kube-system
```
Viewing the log of the fluentd
```
kubectl logs $(kubectl get pods --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}' -n kube-system | grep fluentd) -n kube-system
```
Showing the Minikube IP
`echo "Minikube IP: $(minikube ip)"`
Showing the Kibana Port
`kubectl describe svc kibana -n logging | grep NodePort`
## Interacting with the API
Showing the URL
```
echo "URL: $(minikube ip):$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].nodePort}')"
```
Retrieving a static URL
```
curl \
-H "Content-Type: application/json" \
-X POST \
-d '{"ambiente": "2", "uf": "23", "emissao": "20190621","documento": "68830611000","modelo": "63","serie": "001","tipoEmissao": "1","numeroDocumentoFiscal": "13","cbp": "12345678"}' \
http://<url>/api/qrcode
```
Retrieving a dynamic URL
```
curl \
-H "Content-Type: application/json" \
-X POST \
-d '{"ambiente": "2", "uf": "23", "emissao": "20190621","documento": "68830611000","modelo": "63","serie": "001","tipoEmissao": "1","numeroDocumentoFiscal": "13"}' \
http://<url>/api/qrcode
```

View File

@ -0,0 +1,13 @@
FROM openjdk:8u212-jre-alpine
RUN apk add --update \
curl \
&& rm -rf /var/cache/apk/*
ENV AB_OFF=true
ENV JAEGER_SERVICE_NAME=bpe-api\
JAEGER_ENDPOINT=http://jaeger-collector.istio-system.svc:14268/api/traces\
JAEGER_PROPAGATION=b3\
JAEGER_SAMPLER_TYPE=const\
JAEGER_SAMPLER_PARAM=1
EXPOSE 8080 8778 9779 5006
ADD target/*.jar /app.jar
CMD java -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5006 -Djava.net.preferIPv4Stack=true -jar /app.jar

View File

@ -0,0 +1,11 @@
FROM openjdk:8u212-jre-alpine
RUN apk add --update \
curl \
&& rm -rf /var/cache/apk/*
ENV AB_OFF=true
ENV JAEGER_SERVICE_NAME=bpe-api\
JAEGER_SAMPLER_TYPE=const\
JAEGER_SAMPLER_PARAM=1
EXPOSE 8080 8778 9779 5006
ADD ./target/*.jar /app.jar
CMD java -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5006 -Djava.net.preferIPv4Stack=true -jar /app.jar

181
bpe-api/pom.xml 100755
View File

@ -0,0 +1,181 @@
<?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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>br.com.sample</groupId>
<artifactId>bpe-api</artifactId>
<name>BPe API</name>
<version>1.0.11</version>
<packaging>war</packaging>
<properties>
<version.thorntail>2.4.0.Final</version.thorntail>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<failOnMissingWebXml>false</failOnMissingWebXml>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.thorntail</groupId>
<artifactId>bom-all</artifactId>
<version>${version.thorntail}</version>
<scope>import</scope>
<type>pom</type>
</dependency>
<dependency>
<groupId>io.thorntail</groupId>
<artifactId>thorntail-runner</artifactId>
<version>${version.thorntail}</version>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<finalName>bpe-api</finalName>
<plugins>
<plugin>
<groupId>io.thorntail</groupId>
<artifactId>thorntail-maven-plugin</artifactId>
<version>${version.thorntail}</version>
<executions>
<execution>
<goals>
<goal>package</goal>
</goals>
</execution>
</executions>
<configuration>
<properties>
<java.net.preferIPv4Stack>true</java.net.preferIPv4Stack>
</properties>
<jvmArguments>
<jvmArgument>-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5006</jvmArgument>
</jvmArguments>
</configuration>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.3</version>
<configuration>
<archive>
<manifest>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
<addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.31.0</version>
<configuration>
<images>
<image>
<name>${project.build.finalName}:${project.version}</name>
<build>
<dockerFile>${project.basedir}/${dockerfile}</dockerFile>
</build>
</image>
</images>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12</version>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.22.0</version>
<configuration>
<includes>
<include>**/*Test</include>
</includes>
</configuration>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>io.thorntail</groupId>
<artifactId>microprofile-jwt</artifactId>
</dependency>
<dependency>
<groupId>io.thorntail</groupId>
<artifactId>microprofile</artifactId>
</dependency>
<dependency>
<groupId>io.thorntail</groupId>
<artifactId>microprofile-restclient</artifactId>
</dependency>
<dependency>
<groupId>io.thorntail</groupId>
<artifactId>microprofile-metrics</artifactId>
</dependency>
<dependency>
<groupId>io.thorntail</groupId>
<artifactId>microprofile-opentracing</artifactId>
</dependency>
<dependency>
<groupId>io.thorntail</groupId>
<artifactId>jaxrs</artifactId>
</dependency>
<dependency>
<groupId>io.thorntail</groupId>
<artifactId>jaeger</artifactId>
</dependency>
<dependency>
<groupId>io.thorntail</groupId>
<artifactId>microprofile-fault-tolerance</artifactId>
</dependency>
<dependency>
<groupId>io.thorntail</groupId>
<artifactId>microprofile-health</artifactId>
</dependency>
<dependency>
<groupId>io.thorntail</groupId>
<artifactId>microprofile-config</artifactId>
</dependency>
<dependency>
<groupId>io.thorntail</groupId>
<artifactId>fluentd</artifactId>
</dependency>
<dependency>
<groupId>io.thorntail</groupId>
<artifactId>arquillian</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<profiles>
<profile>
<id>normal</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<dockerfile>DockerfileNormal</dockerfile>
</properties>
</profile>
<profile>
<id>istio</id>
<properties>
<dockerfile>DockerfileIstio</dockerfile>
</properties>
</profile>
</profiles>
</project>

View File

@ -0,0 +1,107 @@
package br.com.sample.bean;
import com.fasterxml.jackson.annotation.JsonIgnore;
public class ChaveBean {
private String uf;
private String emissao;
private String documento;
private String modelo;
private String serie;
private String tipoEmissao;
private String numeroDocumentoFiscal;
private String cbp;
public ChaveBean() {
}
public String getUf() {
return uf;
}
public void setUf(String uf) {
this.uf = uf;
}
public String getEmissao() {
return emissao;
}
public void setEmissao(String emissao) {
this.emissao = emissao;
}
public String getDocumento() {
return documento;
}
public void setDocumento(String documento) {
this.documento = documento;
}
public String getModelo() {
return modelo;
}
public void setModelo(String modelo) {
this.modelo = modelo;
}
public String getSerie() {
return serie;
}
public void setSerie(String serie) {
this.serie = serie;
}
public String getTipoEmissao() {
return tipoEmissao;
}
public void setTipoEmissao(String tipoEmissao) {
this.tipoEmissao = tipoEmissao;
}
public String getNumeroDocumentoFiscal() {
return numeroDocumentoFiscal;
}
public void setNumeroDocumentoFiscal(String numeroDocumentoFiscal) {
this.numeroDocumentoFiscal = numeroDocumentoFiscal;
}
public String getCbp() {
return cbp;
}
public void setCbp(String cbp) {
this.cbp = cbp;
}
@JsonIgnore
public boolean isValid() {
return (uf != null
&& emissao != null
&& documento != null
&& modelo != null
&& serie != null
&& tipoEmissao != null
&& numeroDocumentoFiscal != null);
}
@Override
public String toString() {
return "ChaveBean{" +
"uf='" + uf + '\'' +
", emissao='" + emissao + '\'' +
", documento='" + documento + '\'' +
", modelo='" + modelo + '\'' +
", serie='" + serie + '\'' +
", tipoEmissao='" + tipoEmissao + '\'' +
", numeroDocumentoFiscal='" + numeroDocumentoFiscal + '\'' +
", cbp='" + cbp + '\'' +
'}';
}
}

View File

@ -0,0 +1,118 @@
package br.com.sample.bean;
import com.fasterxml.jackson.annotation.JsonIgnore;
public class QRCodeBean {
private String ambiente;
private String uf;
private String emissao;
private String documento;
private String modelo;
private String serie;
private String tipoEmissao;
private String numeroDocumentoFiscal;
private String cbp;
public QRCodeBean() {
}
public String getAmbiente() {
return ambiente;
}
public void setAmbiente(String ambiente) {
this.ambiente = ambiente;
}
public String getUf() {
return uf;
}
public void setUf(String uf) {
this.uf = uf;
}
public String getEmissao() {
return emissao;
}
public void setEmissao(String emissao) {
this.emissao = emissao;
}
public String getDocumento() {
return documento;
}
public void setDocumento(String documento) {
this.documento = documento;
}
public String getModelo() {
return modelo;
}
public void setModelo(String modelo) {
this.modelo = modelo;
}
public String getSerie() {
return serie;
}
public void setSerie(String serie) {
this.serie = serie;
}
public String getTipoEmissao() {
return tipoEmissao;
}
public void setTipoEmissao(String tipoEmissao) {
this.tipoEmissao = tipoEmissao;
}
public String getNumeroDocumentoFiscal() {
return numeroDocumentoFiscal;
}
public void setNumeroDocumentoFiscal(String numeroDocumentoFiscal) {
this.numeroDocumentoFiscal = numeroDocumentoFiscal;
}
public String getCbp() {
return cbp;
}
public void setCbp(String cbp) {
this.cbp = cbp;
}
@JsonIgnore
public boolean isValid() {
return (ambiente != null
&& uf != null
&& emissao != null
&& documento != null
&& modelo != null
&& serie != null
&& tipoEmissao != null
&& numeroDocumentoFiscal != null);
}
@Override
public String toString() {
return "QRCodeBean{" +
"ambiente='" + ambiente + '\'' +
", uf='" + uf + '\'' +
", emissao='" + emissao + '\'' +
", documento='" + documento + '\'' +
", modelo='" + modelo + '\'' +
", serie='" + serie + '\'' +
", tipoEmissao='" + tipoEmissao + '\'' +
", numeroDocumentoFiscal='" + numeroDocumentoFiscal + '\'' +
", cbp='" + cbp + '\'' +
'}';
}
}

View File

@ -0,0 +1,77 @@
package br.com.sample.controller;
import io.opentracing.Tracer;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.eclipse.microprofile.faulttolerance.*;
import org.eclipse.microprofile.metrics.annotation.Counted;
import org.eclipse.microprofile.opentracing.ClientTracingRegistrar;
import org.eclipse.microprofile.opentracing.Traced;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.json.Json;
import javax.json.JsonObject;
import javax.json.JsonObjectBuilder;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
@ApplicationScoped
@Traced(value = true, operationName = "ChaveController")
public class ChaveController {
private final Logger logger = LoggerFactory.getLogger(getClass());
@Inject
@ConfigProperty(name = "bpechave.api.url", defaultValue = "http://bpe-chave:8080/")
private String bpechaveURL;
@Inject
@ConfigProperty(name = "app.name")
private String app;
@Inject
private Tracer tracer;
@Counted
@Timeout(3000)
@Bulkhead(value = 2, waitingTaskQueue = 10)
@Fallback(fallbackMethod = "getChaveBeanFallBack")
public JsonObject getChaveBean(final String correlationId, final String beanJsonString) {
final JsonObjectBuilder jsonBuilder = Json.createObjectBuilder();
jsonBuilder.add("correlation-id", correlationId);
jsonBuilder.add("message", String.format("Calling %s", bpechaveURL));
jsonBuilder.add("bean", beanJsonString);
JsonObject json = jsonBuilder.build();
tracer.activeSpan().log(json.toString());
Client client = ClientTracingRegistrar.configure(ClientBuilder.newBuilder()).build();
final Response response = client.target(bpechaveURL)
.path("chave")
.path("bean")
.request(MediaType.APPLICATION_JSON_TYPE)
.header("x-correlation-id", correlationId)
.post(Entity.json(beanJsonString));
return response.readEntity(JsonObject.class);
}
public JsonObject getChaveBeanFallBack(final String correlationId, final String beanJsonString) {
JsonObjectBuilder jsonBuilder = Json.createObjectBuilder();
jsonBuilder.add("correlation-id", correlationId);
jsonBuilder.add("chbpe", "NA");
jsonBuilder.add("app", app);
JsonObject json = jsonBuilder.build();
logger.info(json.toString());
return json;
}
}

View File

@ -0,0 +1,80 @@
package br.com.sample.controller;
import io.opentracing.Tracer;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.eclipse.microprofile.faulttolerance.Bulkhead;
import org.eclipse.microprofile.faulttolerance.Fallback;
import org.eclipse.microprofile.faulttolerance.Retry;
import org.eclipse.microprofile.faulttolerance.Timeout;
import org.eclipse.microprofile.metrics.annotation.Counted;
import org.eclipse.microprofile.opentracing.ClientTracingRegistrar;
import org.eclipse.microprofile.opentracing.Traced;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.json.Json;
import javax.json.JsonObject;
import javax.json.JsonObjectBuilder;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
@ApplicationScoped
@Traced(value = true, operationName = "QRCodeController")
public class QRCodeController {
private final Logger logger = LoggerFactory.getLogger(getClass());
@Inject
@ConfigProperty(name = "bpeqrcode.api.url", defaultValue = "http://bpe-qrcode:8080/")
private String bpeqrcodeURL;
@Inject
@ConfigProperty(name = "app.name")
private String app;
@Inject
private Tracer tracer;
@Counted
@Timeout(3000)
@Bulkhead(value = 2, waitingTaskQueue = 10)
@Fallback(fallbackMethod = "getQRCodeBeanFallBack")
public JsonObject getQRCodeBean(final String correlationId, final String beanJsonString) {
final JsonObjectBuilder jsonBuilder = Json.createObjectBuilder();
jsonBuilder.add("correlation-id", correlationId);
jsonBuilder.add("message", String.format("Calling %s", bpeqrcodeURL));
jsonBuilder.add("bean", beanJsonString);
JsonObject json = jsonBuilder.build();
tracer.activeSpan().log(json.toString());
Client client = ClientTracingRegistrar.configure(ClientBuilder.newBuilder()).build();
final Response response = client.target(bpeqrcodeURL)
.path("qrcode")
.path("bean")
.request(MediaType.APPLICATION_JSON_TYPE)
.header("x-correlation-id", correlationId)
.post(Entity.json(beanJsonString));
return response.readEntity(JsonObject.class);
}
public JsonObject getQRCodeBeanFallBack(final String correlationId, final String beanJsonString) {
JsonObjectBuilder jsonBuilder = Json.createObjectBuilder();
jsonBuilder.add("correlation-id", correlationId);
jsonBuilder.add("qrcode", "NA");
jsonBuilder.add("app", app);
JsonObject json = jsonBuilder.build();
logger.info(json.toString());
return json;
}
}

View File

@ -0,0 +1,126 @@
package br.com.sample.rest;
import br.com.sample.bean.ChaveBean;
import br.com.sample.controller.ChaveController;
import br.com.sample.util.CorrelationUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.eclipse.microprofile.metrics.annotation.Counted;
import org.eclipse.microprofile.metrics.annotation.Timed;
import org.eclipse.microprofile.opentracing.Traced;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.json.Json;
import javax.json.JsonObject;
import javax.json.JsonObjectBuilder;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
@ApplicationScoped
@Path("/")
@Traced
public class ApiBPeChaveEndPoint {
private final Logger logger = LoggerFactory.getLogger(getClass());
private static final ObjectMapper om = new ObjectMapper();
@Inject
private ChaveController chaveController;
@Inject
private CorrelationUtils correlationUtils;
@Inject
@ConfigProperty(name = "bpechave.api.url", defaultValue = "http://bpe-chave:8080/")
private String bpechaveURL;
@Inject
@ConfigProperty(name = "app.name")
private String app;
@POST
@Counted(monotonic = true, name = "bpeapi-bpechave-count", absolute = true)
@Timed(name = "bpeapi-bpechave-time", absolute = true)
@Path("chave")
@Produces({MediaType.APPLICATION_JSON})
@Consumes(MediaType.APPLICATION_JSON)
public Response doGetChaveBean(ChaveBean bean) {
String correlationId = correlationUtils.getCorrelationId();
final JsonObjectBuilder jsonBuilder = Json.createObjectBuilder();
JsonObject obj = null;
if (!bean.isValid()) {
jsonBuilder.add("correlation-id", correlationId);
jsonBuilder.add("message", "Parâmetros inválidos");
jsonBuilder.add("bean", bean.toString());
jsonBuilder.add("app", app);
obj = jsonBuilder.build();
logger.error(obj.toString());
return Response.status(Response.Status.BAD_REQUEST).entity(obj).build();
}
String chave = "NA";
String beanJsonString = null;
try {
beanJsonString = om.writeValueAsString(bean);
} catch (Exception e) {
jsonBuilder.add("correlation-id", correlationId);
jsonBuilder.add("exception", e.toString());
jsonBuilder.add("bean", bean.toString());
jsonBuilder.add("app", app);
obj = jsonBuilder.build();
logger.error(obj.toString());
return Response.status(Response.Status.BAD_REQUEST).entity(obj).build();
}
try {
obj = chaveController.getChaveBean(correlationId, beanJsonString);
chave = obj.getString("chbpe");
} catch (ProcessingException ex) {
String info = ex.toString();
if (ex.getCause() != null) {
info = ex.getCause().getClass().getSimpleName() + ": " + ex.getCause().getMessage();
}
jsonBuilder.add("correlation-id", correlationId);
jsonBuilder.add("message", "Exception trying to get the response from ".concat(bpechaveURL));
jsonBuilder.add("exception", info);
jsonBuilder.add("bean", bean.toString());
jsonBuilder.add("app", app);
obj = jsonBuilder.build();
logger.error(obj.toString(), ex);
return Response
.status(Response.Status.SERVICE_UNAVAILABLE)
.entity(obj)
.build();
}
JsonObjectBuilder json = Json.createObjectBuilder();
json.add("chbpe", chave);
json.add("correlation-id", correlationId);
if (chave.equals("NA")) {
jsonBuilder.add("app", app);
}
return Response.ok(json.build()).build();
}
}

View File

@ -0,0 +1,118 @@
package br.com.sample.rest;
import br.com.sample.bean.QRCodeBean;
import br.com.sample.controller.QRCodeController;
import br.com.sample.util.CorrelationUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.eclipse.microprofile.metrics.annotation.Counted;
import org.eclipse.microprofile.metrics.annotation.Timed;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.json.Json;
import javax.json.JsonObject;
import javax.json.JsonObjectBuilder;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
@ApplicationScoped
@Path("/")
public class ApiBPeQRCodeEndPoint {
private final Logger logger = LoggerFactory.getLogger(getClass());
private static final ObjectMapper om = new ObjectMapper();
@Inject
private QRCodeController qrcodeController;
@Inject
private CorrelationUtils correlationUtils;
@Inject
@ConfigProperty(name = "bpeqrcode.api.url", defaultValue = "http://bpe-qrcode:8080/")
private String bpeqrcodeURL;
@Inject
@ConfigProperty(name = "app.name")
private String app;
@POST
@Counted(monotonic = true, name = "bpeapi-bpeqrcode-count", absolute = true)
@Timed(name = "bpeapi-bpeqrcode-time", absolute = true)
@Path("qrcode")
@Produces({MediaType.APPLICATION_JSON})
@Consumes(MediaType.APPLICATION_JSON)
public Response doGetQRCode(QRCodeBean bean) {
String correlationId = correlationUtils.getCorrelationId();
final JsonObjectBuilder jsonBuilder = Json.createObjectBuilder();
JsonObject obj = null;
if (!bean.isValid()) {
jsonBuilder.add("correlation-id", correlationId);
jsonBuilder.add("message", "Parâmetros inválidos");
jsonBuilder.add("bean", bean.toString());
jsonBuilder.add("app", app);
obj = jsonBuilder.build();
logger.error(obj.toString());
return Response.status(Response.Status.BAD_REQUEST).entity(obj).build();
}
String beanJsonString = null;
try {
beanJsonString = om.writeValueAsString(bean);
} catch (Exception e) {
jsonBuilder.add("correlation-id", correlationId);
jsonBuilder.add("exception", e.toString());
jsonBuilder.add("bean", bean.toString());
jsonBuilder.add("app", app);
obj = jsonBuilder.build();
logger.error(obj.toString());
return Response.status(Response.Status.BAD_REQUEST).entity(obj).build();
}
try {
obj = qrcodeController.getQRCodeBean(correlationId, beanJsonString);
obj.forEach(jsonBuilder::add);
jsonBuilder.add("correlation-id", correlationId);
obj = jsonBuilder.build();
} catch (ProcessingException ex) {
String info = ex.toString();
if (ex.getCause() != null) {
info = ex.getCause().getClass().getSimpleName() + ": " + ex.getCause().getMessage();
}
jsonBuilder.add("correlation-id", correlationId);
jsonBuilder.add("message", "Exception trying to get the response from ".concat(bpeqrcodeURL));
jsonBuilder.add("exception", info);
jsonBuilder.add("bean", bean.toString());
jsonBuilder.add("app", app);
obj = jsonBuilder.build();
logger.warn(obj.toString(), ex);
return Response
.status(Response.Status.SERVICE_UNAVAILABLE)
.entity(obj)
.build();
}
return Response.ok(obj).build();
}
}

View File

@ -0,0 +1,73 @@
package br.com.sample.rest;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.eclipse.microprofile.metrics.annotation.Counted;
import org.eclipse.microprofile.metrics.annotation.Timed;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.json.Json;
import javax.json.JsonObjectBuilder;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.InputStream;
import java.util.Properties;
@ApplicationScoped
@Path("/")
public class ApiVersaoEndPoint {
private final Logger logger = LoggerFactory.getLogger(getClass());
@Inject
@ConfigProperty(name = "ambiente", defaultValue = "2")
private String ambiente;
@GET
@Counted(monotonic = true, name = "bpeapi-versao-count", absolute = true)
@Timed(name = "bpeapi-versao-time", absolute = true)
@Path("versao")
@Produces({MediaType.APPLICATION_JSON})
public Response doGetversao() {
JsonObjectBuilder json = Json.createObjectBuilder();
json.add("versao", getVersion());
json.add("ambiente", ambiente);
return Response.ok(json.build()).build();
}
public synchronized String getVersion() {
String version = null;
try {
Properties p = new Properties();
InputStream is = getClass().getResourceAsStream("/META-INF/maven/br.com.trevezani/bpe-api/pom.properties");
if (is != null) {
p.load(is);
version = p.getProperty("version", "");
}
} catch (Exception e) {
}
// fallback to using Java API
if (version == null) {
Package aPackage = getClass().getPackage();
if (aPackage != null) {
version = aPackage.getImplementationVersion();
if (version == null) {
version = aPackage.getSpecificationVersion();
}
}
}
if (version == null) {
version = "1DF";
}
return version;
}
}

View File

@ -0,0 +1,9 @@
package br.com.sample.rest;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
@ApplicationPath("/api")
public class RestApplication extends Application {
}

View File

@ -0,0 +1,28 @@
package br.com.sample.rest;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.eclipse.microprofile.health.Health;
import org.eclipse.microprofile.health.HealthCheck;
import org.eclipse.microprofile.health.HealthCheckResponse;
import org.eclipse.microprofile.health.HealthCheckResponseBuilder;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
@Health
@ApplicationScoped
public class ServiceHealthCheck implements HealthCheck {
@Inject
@ConfigProperty(name = "app.name")
private String app;
@Override
public HealthCheckResponse call() {
HealthCheckResponseBuilder responseBuilder = HealthCheckResponse.named(app);
responseBuilder.withData("memory", Runtime.getRuntime().freeMemory());
responseBuilder.withData("availableProcessors", Runtime.getRuntime().availableProcessors());
return responseBuilder.state(true).build();
}
}

View File

@ -0,0 +1,13 @@
package br.com.sample.util;
import javax.enterprise.context.ApplicationScoped;
import java.util.UUID;
@ApplicationScoped
public class CorrelationUtils {
public String getCorrelationId() {
return UUID.randomUUID().toString();
}
}

View File

@ -0,0 +1 @@
app.name=bpe-api

View File

@ -0,0 +1,10 @@
thorntail:
jaeger:
service-name: bpe-api
sampler-type: const
sampler-parameter: 1
fluentd:
hostname: localhost
level: INFO
port: 24224
tag: bpe-api

View File

@ -0,0 +1,7 @@
thorntail:
jaeger:
service-name: bpe-api
sampler-type: const
sampler-parameter: 1
enable-b3-header-propagation: true
remote-reporter-http-endpoint: 'http://jaeger-collector.istio-system:14268/api/traces'

View File

@ -0,0 +1,13 @@
FROM openjdk:8u212-jre-alpine
RUN apk add --update \
curl \
&& rm -rf /var/cache/apk/*
ENV AB_OFF=true
ENV JAEGER_SERVICE_NAME=bpe-chave\
JAEGER_ENDPOINT=http://jaeger-collector.istio-system.svc:14268/api/traces\
JAEGER_PROPAGATION=b3\
JAEGER_SAMPLER_TYPE=const\
JAEGER_SAMPLER_PARAM=1
EXPOSE 8080 8778 9779 5006
ADD target/*.jar /app.jar
CMD java -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5006 -Djava.net.preferIPv4Stack=true -jar /app.jar

View File

@ -0,0 +1,11 @@
FROM openjdk:8u212-jre-alpine
RUN apk add --update \
curl \
&& rm -rf /var/cache/apk/*
ENV AB_OFF=true
ENV JAEGER_SERVICE_NAME=bpe-chave\
JAEGER_SAMPLER_TYPE=const\
JAEGER_SAMPLER_PARAM=1
EXPOSE 8080 8778 9779 5006
ADD target/*.jar /app.jar
CMD java -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5006 -Djava.net.preferIPv4Stack=true -jar /app.jar

182
bpe-chave/pom.xml 100755
View File

@ -0,0 +1,182 @@
<?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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>br.com.sample</groupId>
<artifactId>bpe-chave</artifactId>
<name>BPe Chave</name>
<version>1.0.11</version>
<packaging>war</packaging>
<properties>
<version.thorntail>2.4.0.Final</version.thorntail>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<failOnMissingWebXml>false</failOnMissingWebXml>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.thorntail</groupId>
<artifactId>bom-all</artifactId>
<version>${version.thorntail}</version>
<scope>import</scope>
<type>pom</type>
</dependency>
<dependency>
<groupId>io.thorntail</groupId>
<artifactId>thorntail-runner</artifactId>
<version>${version.thorntail}</version>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<finalName>bpe-chave</finalName>
<plugins>
<plugin>
<groupId>io.thorntail</groupId>
<artifactId>thorntail-maven-plugin</artifactId>
<version>${version.thorntail}</version>
<executions>
<execution>
<goals>
<goal>package</goal>
</goals>
</execution>
</executions>
<configuration>
<properties>
<java.net.preferIPv4Stack>true</java.net.preferIPv4Stack>
</properties>
<jvmArguments>
<jvmArgument>-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5006</jvmArgument>
</jvmArguments>
</configuration>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.3</version>
<configuration>
<archive>
<manifest>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
<addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.28.0</version>
<configuration>
<images>
<image>
<name>${project.build.finalName}:${project.version}</name>
<build>
<dockerFile>${project.basedir}/${dockerfile}</dockerFile>
</build>
</image>
</images>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12</version>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.22.0</version>
<configuration>
<includes>
<include>**/*Test</include>
</includes>
</configuration>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>io.thorntail</groupId>
<artifactId>microprofile-jwt</artifactId>
</dependency>
<dependency>
<groupId>io.thorntail</groupId>
<artifactId>microprofile</artifactId>
</dependency>
<dependency>
<groupId>io.thorntail</groupId>
<artifactId>microprofile-restclient</artifactId>
</dependency>
<dependency>
<groupId>io.thorntail</groupId>
<artifactId>microprofile-metrics</artifactId>
</dependency>
<dependency>
<groupId>io.thorntail</groupId>
<artifactId>microprofile-opentracing</artifactId>
</dependency>
<dependency>
<groupId>io.thorntail</groupId>
<artifactId>jaxrs</artifactId>
</dependency>
<dependency>
<groupId>io.thorntail</groupId>
<artifactId>jaeger</artifactId>
</dependency>
<dependency>
<groupId>io.thorntail</groupId>
<artifactId>microprofile-fault-tolerance</artifactId>
</dependency>
<dependency>
<groupId>io.thorntail</groupId>
<artifactId>microprofile-health</artifactId>
</dependency>
<dependency>
<groupId>io.thorntail</groupId>
<artifactId>microprofile-config</artifactId>
</dependency>
<dependency>
<groupId>io.thorntail</groupId>
<artifactId>fluentd</artifactId>
</dependency>
<dependency>
<groupId>io.thorntail</groupId>
<artifactId>arquillian</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<profiles>
<profile>
<id>normal</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<dockerfile>DockerfileNormal</dockerfile>
</properties>
</profile>
<profile>
<id>istio</id>
<properties>
<dockerfile>DockerfileIstio</dockerfile>
</properties>
</profile>
</profiles>
</project>

View File

@ -0,0 +1,107 @@
package br.com.sample.bean;
import com.fasterxml.jackson.annotation.JsonIgnore;
public class ChaveBean {
private String uf;
private String emissao;
private String documento;
private String modelo;
private String serie;
private String tipoEmissao;
private String numeroDocumentoFiscal;
private String cbp;
public ChaveBean() {
}
public String getUf() {
return uf;
}
public void setUf(String uf) {
this.uf = uf;
}
public String getEmissao() {
return emissao;
}
public void setEmissao(String emissao) {
this.emissao = emissao;
}
public String getDocumento() {
return documento;
}
public void setDocumento(String documento) {
this.documento = documento;
}
public String getModelo() {
return modelo;
}
public void setModelo(String modelo) {
this.modelo = modelo;
}
public String getSerie() {
return serie;
}
public void setSerie(String serie) {
this.serie = serie;
}
public String getTipoEmissao() {
return tipoEmissao;
}
public void setTipoEmissao(String tipoEmissao) {
this.tipoEmissao = tipoEmissao;
}
public String getNumeroDocumentoFiscal() {
return numeroDocumentoFiscal;
}
public void setNumeroDocumentoFiscal(String numeroDocumentoFiscal) {
this.numeroDocumentoFiscal = numeroDocumentoFiscal;
}
public String getCbp() {
return cbp;
}
public void setCbp(String cbp) {
this.cbp = cbp;
}
@JsonIgnore
public boolean isValid() {
return (uf != null
&& emissao != null
&& documento != null
&& modelo != null
&& serie != null
&& tipoEmissao != null
&& numeroDocumentoFiscal != null);
}
@Override
public String toString() {
return "ChaveBean{" +
"uf='" + uf + '\'' +
", emissao='" + emissao + '\'' +
", documento='" + documento + '\'' +
", modelo='" + modelo + '\'' +
", serie='" + serie + '\'' +
", tipoEmissao='" + tipoEmissao + '\'' +
", numeroDocumentoFiscal='" + numeroDocumentoFiscal + '\'' +
", cbp='" + cbp + '\'' +
'}';
}
}

View File

@ -0,0 +1,48 @@
package br.com.sample.controller;
import br.com.sample.util.Modulo11;
import br.com.sample.util.StringUtils;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.validation.constraints.NotNull;
import java.util.Random;
@ApplicationScoped
public class ChaveController {
@Inject
private StringUtils stringUtils;
@Inject
private Modulo11 modulo11;
public String getChaveBPe(@NotNull String uf, @NotNull String emissao, @NotNull String documento,
@NotNull String modelo, @NotNull String serie, @NotNull String tipoEmissao,
@NotNull String numeroDocumentoFiscal, String cbp) {
if (cbp == null) {
cbp = String.valueOf(new Random().nextInt(99999999));
}
// YYYYMMDD
String ano = emissao.substring(2, 4);
String mes = emissao.substring(5, 7);
StringBuilder chave = new StringBuilder();
chave.append(uf);
chave.append(ano);
chave.append(mes);
chave.append(stringUtils.lpadTo(documento.replaceAll("\\D", ""), 14, '0'));
chave.append(modelo);
chave.append(stringUtils.lpadTo(serie, 3, '0'));
chave.append(stringUtils.lpadTo(String.valueOf(numeroDocumentoFiscal), 9, '0'));
chave.append(stringUtils.lpadTo(tipoEmissao, 1, '0'));
chave.append(stringUtils.lpadTo(cbp, 8, '0'));
String mod = String.valueOf(modulo11.modulo11(chave.toString()));
chave.append(mod);
return chave.toString();
}
}

View File

@ -0,0 +1,26 @@
package br.com.sample.enums;
import java.util.Arrays;
public enum Ambiente {
Producao("1"),
Homologacao("2");
String codigo;
Ambiente(String codigo) {
this.codigo = codigo;
}
public String getCodigo() {
return this.codigo;
}
public static Ambiente getAmbiente(String codigo) {
Ambiente ambiente = Arrays.stream(Ambiente.values())
.filter(e -> e.getCodigo().equals(codigo))
.findAny()
.orElseThrow(() -> new IllegalStateException(String.format("Unsupported type %s.", codigo)));
return ambiente;
}
}

View File

@ -0,0 +1,96 @@
package br.com.sample.rest;
import br.com.sample.bean.ChaveBean;
import br.com.sample.controller.ChaveController;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.eclipse.microprofile.metrics.annotation.Counted;
import org.eclipse.microprofile.metrics.annotation.Timed;
import org.eclipse.microprofile.openapi.annotations.Operation;
import org.eclipse.microprofile.openapi.annotations.responses.APIResponse;
import org.eclipse.microprofile.openapi.annotations.tags.Tag;
import org.eclipse.microprofile.opentracing.Traced;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.json.Json;
import javax.json.JsonObject;
import javax.json.JsonObjectBuilder;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
@Tag(name = "BPeChave", description = "Microserviço responsável por gerar a chave BPe")
@ApplicationScoped
@Path("chave")
@Traced
public class BPeChaveEndPoint {
private final Logger logger = LoggerFactory.getLogger(getClass());
@Inject
@ConfigProperty(name = "app.name")
private String app;
@Inject
private ChaveController chaveController;
@GET
@Counted(monotonic = true, name = "bpechave-count", absolute = true)
@Timed(name = "bpechave-time", absolute = true)
@Operation(summary = "Gerar chave BPe")
@APIResponse(description = "Chave BPe")
@Path("/{uf}/{emissao}/{documento}/{modelo}/{serie}/{tipoEmissao}/{numeroDocumentoFiscal}/{cbp}")
@Produces({MediaType.APPLICATION_JSON})
public Response doGetChave(@PathParam("uf") String uf, @PathParam("emissao") String emissao,
@PathParam("documento") String documento, @PathParam("modelo") String modelo,
@PathParam("serie") String serie, @PathParam("tipoEmissao") String tipoEmissao,
@PathParam("numeroDocumentoFiscal") String numeroDocumentoFiscal, @PathParam("cbp") String cbp) {
String chave = chaveController.getChaveBPe( uf, emissao, documento, modelo, serie, tipoEmissao, numeroDocumentoFiscal, cbp);
JsonObjectBuilder json = Json.createObjectBuilder();
json.add("chbpe", chave);
return Response.ok(json.build()).build();
}
@POST
@Counted(monotonic = true, name = "bpechave-count", absolute = true)
@Timed(name = "bpechave-time", absolute = true)
@Path("bean")
@Operation(summary = "Gerar chave BPe via JSON")
@APIResponse(description = "Chave BPe")
@Produces({MediaType.APPLICATION_JSON})
@Consumes(MediaType.APPLICATION_JSON)
public Response doGetChaveBean(@HeaderParam("x-correlation-id") String correlationId, ChaveBean bean) {
final JsonObjectBuilder jsonBuilder = Json.createObjectBuilder();
if (!bean.isValid()) {
jsonBuilder.add("correlation-id", correlationId);
jsonBuilder.add("message", "Parâmetros inválidos");
jsonBuilder.add("bean", bean.toString());
jsonBuilder.add("app", app);
JsonObject json = jsonBuilder.build();
logger.error(json.toString());
return Response.status(Response.Status.BAD_REQUEST).entity(json).build();
}
String chave = chaveController.getChaveBPe( bean.getUf(), bean.getEmissao(), bean.getDocumento(), bean.getModelo(),
bean.getSerie(), bean.getTipoEmissao(), bean.getNumeroDocumentoFiscal(), bean.getCbp());
JsonObjectBuilder json = Json.createObjectBuilder();
json.add("chbpe", chave);
final JsonObjectBuilder jsonBuilderLog = Json.createObjectBuilder();
jsonBuilderLog.add("correlation-id", correlationId);
jsonBuilderLog.add("message", String.format("Chave gerada [%s]", chave));
jsonBuilderLog.add("app", app);
logger.info(jsonBuilderLog.build().toString());
return Response.ok(json.build()).build();
}
}

View File

@ -0,0 +1,9 @@
package br.com.sample.rest;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
@ApplicationPath("/")
public class RestApplication extends Application {
}

View File

@ -0,0 +1,28 @@
package br.com.sample.rest;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.eclipse.microprofile.health.Health;
import org.eclipse.microprofile.health.HealthCheck;
import org.eclipse.microprofile.health.HealthCheckResponse;
import org.eclipse.microprofile.health.HealthCheckResponseBuilder;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
@Health
@ApplicationScoped
public class ServiceHealthCheck implements HealthCheck {
@Inject
@ConfigProperty(name = "app.name")
private String app;
@Override
public HealthCheckResponse call() {
HealthCheckResponseBuilder responseBuilder = HealthCheckResponse.named(app);
responseBuilder.withData("memory", Runtime.getRuntime().freeMemory());
responseBuilder.withData("availableProcessors", Runtime.getRuntime().availableProcessors());
return responseBuilder.state(true).build();
}
}

View File

@ -0,0 +1,24 @@
package br.com.sample.util;
import javax.enterprise.context.ApplicationScoped;
@ApplicationScoped
public class Modulo11 {
public int modulo11(String chave) {
int total = 0;
int peso = 2;
for (int i = 0; i < chave.length(); i++) {
total += (chave.charAt((chave.length() - 1) - i) - '0') * peso;
peso++;
if (peso == 10)
peso = 2;
}
int resto = total % 11;
return (resto == 0 || resto == 1) ? 0 : (11 - resto);
}
}

View File

@ -0,0 +1,23 @@
package br.com.sample.util;
import javax.enterprise.context.ApplicationScoped;
@ApplicationScoped
public class StringUtils {
public String lpadTo(String input, int width, char ch) {
String strPad = "";
StringBuffer sb = new StringBuffer(input.trim());
while (sb.length() < width)
sb.insert(0, ch);
strPad = sb.toString();
if (strPad.length() > width) {
strPad = strPad.substring(0, width);
}
return strPad;
}
}

View File

@ -0,0 +1 @@
app.name=bpe-chave

View File

@ -0,0 +1,10 @@
thorntail:
jaeger:
service-name: bpe-chave
sampler-type: const
sampler-parameter: 1
fluentd:
hostname: localhost
level: INFO
port: 24224
tag: bpe-chave

View File

@ -0,0 +1,7 @@
thorntail:
jaeger:
service-name: bpe-chave
sampler-type: const
sampler-parameter: 1
enable-b3-header-propagation: true
remote-reporter-http-endpoint: 'http://jaeger-collector.istio-system:14268/api/traces'

View File

@ -0,0 +1,132 @@
package test.rest;
import br.com.sample.bean.ChaveBean;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.container.test.api.RunAsClient;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.arquillian.junit.InSequence;
import org.jboss.arquillian.test.api.ArquillianResource;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.asset.EmptyAsset;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.jboss.shrinkwrap.resolver.api.maven.Maven;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import javax.json.JsonObject;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.File;
import java.io.IOException;
import java.net.URL;
@RunWith(Arquillian.class)
public class BPeChaveEndPointTest {
@ArquillianResource
private URL webappUrl;
WebTarget target;
ObjectMapper om = new ObjectMapper();
@Before
public void before() throws Exception {
target = ClientBuilder.newClient().target(webappUrl.toURI());
}
@Deployment
public static WebArchive createTestArchive() {
File[] files = Maven.resolver().loadPomFromFile("pom.xml")
.importRuntimeDependencies().resolve().withTransitivity().asFile();
WebArchive war = ShrinkWrap.create(WebArchive.class)
.addAsLibraries(files)
.addPackages(true, "br.com.trevezani.bpechave")
.addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml");
return war;
}
@Test
@RunAsClient
@InSequence(1)
public void testChave() throws IOException {
final Response response = target.path("chave")
.path("23")
.path("20190621")
.path("68830611000")
.path("63")
.path("001")
.path("1")
.path("13")
.path("123")
.request(MediaType.APPLICATION_JSON_TYPE)
.get();
Assert.assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
JsonObject obj = response.readEntity(JsonObject.class);
Assert.assertNotNull("Chave inválida", obj);
System.out.println("Validando o retorno: ".concat(obj.toString()));
Assert.assertEquals("QRCode diferente: ".concat(obj.getString("chbpe")),
"23196200068830611000630010000000131000001230", obj.getString("chbpe"));
}
@Test
@RunAsClient
@InSequence(2)
public void testChaveBean() throws IOException {
ChaveBean bean = new ChaveBean();
bean.setUf("23");
bean.setEmissao("20190621");
bean.setDocumento("68830611000");
bean.setModelo("63");
bean.setSerie("001");
bean.setTipoEmissao("1");
bean.setNumeroDocumentoFiscal("13");
bean.setCbp("123");
String beanJsonString = om.writeValueAsString(bean);
final Response response = target.path("chave")
.path("br.com.trevezani.bean")
.request(MediaType.APPLICATION_JSON_TYPE)
.post(Entity.json(beanJsonString));
Assert.assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
JsonObject obj = response.readEntity(JsonObject.class);
Assert.assertNotNull("Chave inválida", obj);
System.out.println("Validando o retorno: ".concat(obj.toString()));
Assert.assertEquals("QRCode diferente: ".concat(obj.getString("chbpe")),
"23196200068830611000630010000000131000001230", obj.getString("chbpe"));
}
@Test
@RunAsClient
@InSequence(3)
public void testChaveBeanError() throws IOException {
ChaveBean bean = new ChaveBean();
String beanJsonString = om.writeValueAsString(bean);
final Response response = target.path("chave")
.path("br.com.trevezani.bean")
.request(MediaType.APPLICATION_JSON_TYPE)
.post(Entity.json(beanJsonString));
Assert.assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), response.getStatus());
}
}

View File

@ -0,0 +1,13 @@
FROM openjdk:8u212-jre-alpine
RUN apk add --update \
curl \
&& rm -rf /var/cache/apk/*
ENV AB_OFF=true
ENV JAEGER_SERVICE_NAME=bpe-qrcode\
JAEGER_ENDPOINT=http://jaeger-collector.istio-system.svc:14268/api/traces\
JAEGER_PROPAGATION=b3\
JAEGER_SAMPLER_TYPE=const\
JAEGER_SAMPLER_PARAM=1
EXPOSE 8080 8778 9779 5006
ADD target/*.jar /app.jar
CMD java -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5006 -Djava.net.preferIPv4Stack=true -jar /app.jar

View File

@ -0,0 +1,11 @@
FROM openjdk:8u212-jre-alpine
RUN apk add --update \
curl \
&& rm -rf /var/cache/apk/*
ENV AB_OFF=true
ENV JAEGER_SERVICE_NAME=bpe-qrcode\
JAEGER_SAMPLER_TYPE=const\
JAEGER_SAMPLER_PARAM=1
EXPOSE 8080 8778 9779 5006
ADD target/*.jar /app.jar
CMD java -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5006 -Djava.net.preferIPv4Stack=true -jar /app.jar

194
bpe-qrcode/pom.xml 100755
View File

@ -0,0 +1,194 @@
<?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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>br.com.sample</groupId>
<artifactId>bpe-qrcode</artifactId>
<name>BPe QRCode URL</name>
<version>1.0.12</version>
<packaging>war</packaging>
<properties>
<version.thorntail>2.4.0.Final</version.thorntail>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<failOnMissingWebXml>false</failOnMissingWebXml>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.thorntail</groupId>
<artifactId>bom-all</artifactId>
<version>${version.thorntail}</version>
<scope>import</scope>
<type>pom</type>
</dependency>
<dependency>
<groupId>io.thorntail</groupId>
<artifactId>thorntail-runner</artifactId>
<version>${version.thorntail}</version>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<finalName>bpe-qrcode</finalName>
<plugins>
<plugin>
<groupId>io.thorntail</groupId>
<artifactId>thorntail-maven-plugin</artifactId>
<version>${version.thorntail}</version>
<executions>
<execution>
<goals>
<goal>package</goal>
</goals>
</execution>
</executions>
<configuration>
<properties>
<java.net.preferIPv4Stack>true</java.net.preferIPv4Stack>
</properties>
<jvmArguments>
<jvmArgument>-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5006</jvmArgument>
</jvmArguments>
</configuration>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.3</version>
<configuration>
<archive>
<manifest>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
<addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.28.0</version>
<configuration>
<images>
<image>
<name>${project.build.finalName}:${project.version}</name>
<build>
<dockerFile>${project.basedir}/${dockerfile}</dockerFile>
</build>
</image>
</images>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12</version>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.22.0</version>
<configuration>
<includes>
<include>**/*Test</include>
</includes>
</configuration>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>io.thorntail</groupId>
<artifactId>microprofile-jwt</artifactId>
</dependency>
<dependency>
<groupId>io.thorntail</groupId>
<artifactId>microprofile</artifactId>
</dependency>
<!-- <dependency>-->
<!-- <groupId>io.thorntail</groupId>-->
<!-- <artifactId>jaeger</artifactId>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>io.thorntail</groupId>-->
<!-- <artifactId>fluentd</artifactId>-->
<!-- </dependency>-->
<dependency>
<groupId>io.thorntail</groupId>
<artifactId>microprofile-restclient</artifactId>
</dependency>
<dependency>
<groupId>io.thorntail</groupId>
<artifactId>microprofile-metrics</artifactId>
</dependency>
<dependency>
<groupId>io.thorntail</groupId>
<artifactId>microprofile-openapi</artifactId>
</dependency>
<dependency>
<groupId>io.thorntail</groupId>
<artifactId>microprofile-opentracing</artifactId>
</dependency>
<dependency>
<groupId>io.thorntail</groupId>
<artifactId>jaxrs</artifactId>
</dependency>
<dependency>
<groupId>io.thorntail</groupId>
<artifactId>jaeger</artifactId>
</dependency>
<dependency>
<groupId>io.thorntail</groupId>
<artifactId>microprofile-fault-tolerance</artifactId>
</dependency>
<dependency>
<groupId>io.thorntail</groupId>
<artifactId>microprofile-health</artifactId>
</dependency>
<dependency>
<groupId>io.thorntail</groupId>
<artifactId>microprofile-config</artifactId>
</dependency>
<dependency>
<groupId>io.thorntail</groupId>
<artifactId>fluentd</artifactId>
</dependency>
<dependency>
<groupId>io.thorntail</groupId>
<artifactId>arquillian</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<profiles>
<profile>
<id>normal</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<dockerfile>DockerfileNormal</dockerfile>
</properties>
</profile>
<profile>
<id>istio</id>
<properties>
<dockerfile>DockerfileIstio</dockerfile>
</properties>
</profile>
</profiles>
</project>

View File

@ -0,0 +1,107 @@
package br.com.sample.bean;
import com.fasterxml.jackson.annotation.JsonIgnore;
public class ChaveBean {
private String uf;
private String emissao;
private String documento;
private String modelo;
private String serie;
private String tipoEmissao;
private String numeroDocumentoFiscal;
private String cbp;
public ChaveBean() {
}
public String getUf() {
return uf;
}
public void setUf(String uf) {
this.uf = uf;
}
public String getEmissao() {
return emissao;
}
public void setEmissao(String emissao) {
this.emissao = emissao;
}
public String getDocumento() {
return documento;
}
public void setDocumento(String documento) {
this.documento = documento;
}
public String getModelo() {
return modelo;
}
public void setModelo(String modelo) {
this.modelo = modelo;
}
public String getSerie() {
return serie;
}
public void setSerie(String serie) {
this.serie = serie;
}
public String getTipoEmissao() {
return tipoEmissao;
}
public void setTipoEmissao(String tipoEmissao) {
this.tipoEmissao = tipoEmissao;
}
public String getNumeroDocumentoFiscal() {
return numeroDocumentoFiscal;
}
public void setNumeroDocumentoFiscal(String numeroDocumentoFiscal) {
this.numeroDocumentoFiscal = numeroDocumentoFiscal;
}
public String getCbp() {
return cbp;
}
public void setCbp(String cbp) {
this.cbp = cbp;
}
@JsonIgnore
public boolean isValid() {
return (uf != null
&& emissao != null
&& documento != null
&& modelo != null
&& serie != null
&& tipoEmissao != null
&& numeroDocumentoFiscal != null);
}
@Override
public String toString() {
return "ChaveBean{" +
"uf='" + uf + '\'' +
", emissao='" + emissao + '\'' +
", documento='" + documento + '\'' +
", modelo='" + modelo + '\'' +
", serie='" + serie + '\'' +
", tipoEmissao='" + tipoEmissao + '\'' +
", numeroDocumentoFiscal='" + numeroDocumentoFiscal + '\'' +
", cbp='" + cbp + '\'' +
'}';
}
}

View File

@ -0,0 +1,103 @@
package br.com.sample.bean;
import com.fasterxml.jackson.annotation.JsonIgnore;
public class QRCodeBean {
private String ambiente;
private String uf;
private String emissao;
private String documento;
private String modelo;
private String serie;
private String tipoEmissao;
private String numeroDocumentoFiscal;
private String cbp;
public QRCodeBean() {
}
public String getAmbiente() {
return ambiente;
}
public void setAmbiente(String ambiente) {
this.ambiente = ambiente;
}
public String getUf() {
return uf;
}
public void setUf(String uf) {
this.uf = uf;
}
public String getEmissao() {
return emissao;
}
public void setEmissao(String emissao) {
this.emissao = emissao;
}
public String getDocumento() {
return documento;
}
public void setDocumento(String documento) {
this.documento = documento;
}
public String getModelo() {
return modelo;
}
public void setModelo(String modelo) {
this.modelo = modelo;
}
public String getSerie() {
return serie;
}
public void setSerie(String serie) {
this.serie = serie;
}
public String getTipoEmissao() {
return tipoEmissao;
}
public void setTipoEmissao(String tipoEmissao) {
this.tipoEmissao = tipoEmissao;
}
public String getNumeroDocumentoFiscal() {
return numeroDocumentoFiscal;
}
public void setNumeroDocumentoFiscal(String numeroDocumentoFiscal) {
this.numeroDocumentoFiscal = numeroDocumentoFiscal;
}
public String getCbp() {
return cbp;
}
public void setCbp(String cbp) {
this.cbp = cbp;
}
@JsonIgnore
public boolean isValid() {
return (ambiente != null
&& uf != null
&& emissao != null
&& documento != null
&& modelo != null
&& serie != null
&& tipoEmissao != null
&& numeroDocumentoFiscal != null);
}
}

View File

@ -0,0 +1,89 @@
package br.com.sample.controller;
import br.com.sample.enums.Ambiente;
import br.com.sample.enums.QRCodeURL;
import io.opentracing.Tracer;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.eclipse.microprofile.faulttolerance.Bulkhead;
import org.eclipse.microprofile.faulttolerance.Fallback;
import org.eclipse.microprofile.faulttolerance.Retry;
import org.eclipse.microprofile.faulttolerance.Timeout;
import org.eclipse.microprofile.metrics.annotation.Counted;
import org.eclipse.microprofile.opentracing.ClientTracingRegistrar;
import org.eclipse.microprofile.opentracing.Traced;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.json.Json;
import javax.json.JsonObject;
import javax.json.JsonObjectBuilder;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
@ApplicationScoped
@Traced(value = true, operationName = "QRCodeController")
public class QRCodeController {
private final Logger logger = LoggerFactory.getLogger(getClass());
@Inject
@ConfigProperty(name = "app.name")
private String app;
@Inject
@ConfigProperty(name = "bpechave.api.url", defaultValue = "http://bpe-chave:8080/")
private String bpechaveURL;
@Inject
private Tracer tracer;
public String getURL(final String ambienteId, final String ufId) {
Ambiente ambiente = Ambiente.getAmbiente(ambienteId);
String url = QRCodeURL.getURL(ambiente, ufId);
return url;
}
@Counted
@Timeout(3000)
@Bulkhead(value = 2, waitingTaskQueue = 10)
@Fallback(fallbackMethod = "getChaveBeanFallBack")
public JsonObject getChaveBean(final String correlationId, final String beanJsonString) {
final JsonObjectBuilder jsonBuilder = Json.createObjectBuilder();
jsonBuilder.add("correlation-id", correlationId);
jsonBuilder.add("message", String.format("Calling %s", bpechaveURL));
jsonBuilder.add("bean", beanJsonString);
JsonObject json = jsonBuilder.build();
tracer.activeSpan().log(json.toString());
Client client = ClientTracingRegistrar.configure(ClientBuilder.newBuilder()).build();
final Response response = client.target(bpechaveURL)
.path("chave")
.path("bean")
.request(MediaType.APPLICATION_JSON)
.header("x-correlation-id", correlationId)
.post(Entity.json(beanJsonString));
return response.readEntity(JsonObject.class);
}
public JsonObject getChaveBeanFallBack(final String correlationId, final String beanJsonString) {
JsonObjectBuilder jsonBuilder = Json.createObjectBuilder();
jsonBuilder.add("correlation-id", correlationId);
jsonBuilder.add("chbpe", "NA");
jsonBuilder.add("app", app);
JsonObject json = jsonBuilder.build();
logger.info(json.toString());
return json;
}
}

View File

@ -0,0 +1,26 @@
package br.com.sample.enums;
import java.util.Arrays;
public enum Ambiente {
Producao("1"),
Homologacao("2");
String codigo;
Ambiente(String codigo) {
this.codigo = codigo;
}
public String getCodigo() {
return this.codigo;
}
public static Ambiente getAmbiente(String codigo) {
Ambiente ambiente = Arrays.stream(Ambiente.values())
.filter(e -> e.getCodigo().equals(codigo))
.findAny()
.orElseThrow(() -> new IllegalStateException(String.format("Unsupported type %s.", codigo)));
return ambiente;
}
}

View File

@ -0,0 +1,58 @@
package br.com.sample.enums;
import java.util.Arrays;
public enum QRCodeURL {
CE("23", "https://dfe-portal.svrs.rs.gov.br/bpe/qrCode", "https://dfe-portal.sefazvirtual.rs.gov.br/bpe/qrcode"),
RN("24", "https://dfe-portal.svrs.rs.gov.br/bpe/qrCode", "https://dfe-portal.sefazvirtual.rs.gov.br/bpe/qrcode"),
MG("31", "https://bpe.fazenda.mg.gov.br/portalbpe/sistema/qrcode.xhtml", "https://bpe.fazenda.mg.gov.br/portalbpe/sistema/qrcode.xhtml"),
RJ("33", "https://dfe-portal.svrs.rs.gov.br/bpe/qrCode", "https://dfe-portal.sefazvirtual.rs.gov.br/bpe/qrcode");
String uf;
String homologacao;
String producao;
QRCodeURL(String uf, String homologacao, String producao) {
this.uf = uf;
this.homologacao = homologacao;
this.producao = producao;
}
public String getUf() {
return uf;
}
public static QRCodeURL getQRCodeURL(String uf) {
QRCodeURL qr = Arrays.stream(QRCodeURL.values())
.filter(e -> e.getUf().equals(uf))
.findAny()
.orElseThrow(() -> new IllegalStateException(String.format("Unsupported type %s.", uf)));
return qr;
}
public static String getURL(Ambiente ambiente, QRCodeURL qrCodeURL) {
QRCodeURL qr = Arrays.stream(QRCodeURL.values())
.filter(e -> e.name().equals(qrCodeURL.name()))
.findAny()
.orElseThrow(() -> new IllegalStateException(String.format("Unsupported type %s.", qrCodeURL.name())));
if (ambiente.equals(Ambiente.Producao)) {
return qr.producao;
} else {
return qr.homologacao;
}
}
public static String getURL(Ambiente ambiente, String uf) {
QRCodeURL qr = Arrays.stream(QRCodeURL.values())
.filter(e -> e.getUf().equals(uf))
.findAny()
.orElseThrow(() -> new IllegalStateException(String.format("Unsupported type %s.", uf)));
if (ambiente.equals(Ambiente.Producao)) {
return qr.producao;
} else {
return qr.homologacao;
}
}
}

View File

@ -0,0 +1,148 @@
package br.com.sample.rest;
import br.com.sample.bean.ChaveBean;
import br.com.sample.bean.QRCodeBean;
import br.com.sample.controller.QRCodeController;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.eclipse.microprofile.faulttolerance.CircuitBreaker;
import org.eclipse.microprofile.faulttolerance.Fallback;
import org.eclipse.microprofile.faulttolerance.Timeout;
import org.eclipse.microprofile.metrics.annotation.Counted;
import org.eclipse.microprofile.metrics.annotation.Timed;
import org.eclipse.microprofile.opentracing.ClientTracingRegistrar;
import org.eclipse.microprofile.opentracing.Traced;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.json.Json;
import javax.json.JsonObject;
import javax.json.JsonObjectBuilder;
import javax.ws.rs.*;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
@ApplicationScoped
@Path("qrcode")
@Traced
public class QRCodeEndPoint {
private final Logger logger = LoggerFactory.getLogger(getClass());
private static final ObjectMapper om = new ObjectMapper();
@Inject
@ConfigProperty(name = "app.name")
private String app;
@Inject
@ConfigProperty(name = "bpechave.api.url", defaultValue = "http://bpe-chave:8080/")
private String bpechaveURL;
@Inject
private QRCodeController qrcodeController;
@POST
@Counted(monotonic = true, name = "bpeqrcode-count", absolute = true)
@Timed(name = "bpeqrcode-time", absolute = true)
@Path("bean")
@Produces({MediaType.APPLICATION_JSON})
@Consumes(MediaType.APPLICATION_JSON)
public Response doGetQRCode(@HeaderParam("x-correlation-id") String correlationId, QRCodeBean bean) {
final JsonObjectBuilder jsonBuilder = Json.createObjectBuilder();
if (!bean.isValid()) {
jsonBuilder.add("correlation-id", correlationId);
jsonBuilder.add("message", "Parâmetros inválidos");
jsonBuilder.add("bean", bean.toString());
jsonBuilder.add("app", app);
logger.error(jsonBuilder.build().toString());
return Response.status(Response.Status.BAD_REQUEST).entity(jsonBuilder.build()).build();
}
ChaveBean chaveBean = new ChaveBean();
chaveBean.setUf(bean.getUf());
chaveBean.setEmissao(bean.getEmissao());
chaveBean.setDocumento(bean.getDocumento());
chaveBean.setModelo(bean.getModelo());
chaveBean.setSerie(bean.getSerie());
chaveBean.setTipoEmissao(bean.getTipoEmissao());
chaveBean.setNumeroDocumentoFiscal(bean.getNumeroDocumentoFiscal());
chaveBean.setCbp(bean.getCbp());
String chave = getChaveBean(correlationId, chaveBean);
String url = null;
try {
url = qrcodeController.getURL(bean.getAmbiente(), bean.getUf());
} catch (Exception ex) {
jsonBuilder.add("correlation-id", correlationId);
jsonBuilder.add("exception", ex.toString());
jsonBuilder.add("app", app);
JsonObject json = jsonBuilder.build();
logger.error(json.toString(), ex);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(json).build();
}
StringBuilder retorno = new StringBuilder();
retorno.append(url);
retorno.append("?").append("chbpe").append("=").append(chave);
retorno.append("&").append("tpamb").append("=").append(bean.getAmbiente());
JsonObjectBuilder json = Json.createObjectBuilder();
json.add("qrcode", retorno.toString());
return Response.ok(json.build()).build();
}
public String getChaveBean(final String correlationId, ChaveBean bean) {
final JsonObjectBuilder jsonBuilder = Json.createObjectBuilder();
String chave = "NA";
String beanJsonString = null;
try {
beanJsonString = om.writeValueAsString(bean);
} catch (Exception ex) {
String info = ex.toString();
if (ex.getCause() != null) {
info = ex.getCause().getClass().getSimpleName() + ": " + ex.getCause().getMessage();
}
jsonBuilder.add("correlation-id", correlationId);
jsonBuilder.add("exception", info);
jsonBuilder.add("bean", bean.toString());
jsonBuilder.add("app", app);
logger.warn(jsonBuilder.build().toString(), ex);
return "NA";
}
try {
JsonObject obj = qrcodeController.getChaveBean(correlationId, beanJsonString);
chave = obj.getString("chbpe");
} catch (ProcessingException ex) {
jsonBuilder.add("correlation-id", correlationId);
jsonBuilder.add("message", "Exception trying to get the response from ".concat(bpechaveURL));
jsonBuilder.add("exception", ex.toString());
jsonBuilder.add("bean", bean.toString());
jsonBuilder.add("app", app);
logger.warn(jsonBuilder.build().toString(), ex);
}
return chave;
}
}

View File

@ -0,0 +1,9 @@
package br.com.sample.rest;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
@ApplicationPath("/")
public class RestApplication extends Application {
}

View File

@ -0,0 +1,28 @@
package br.com.sample.rest;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.eclipse.microprofile.health.Health;
import org.eclipse.microprofile.health.HealthCheck;
import org.eclipse.microprofile.health.HealthCheckResponse;
import org.eclipse.microprofile.health.HealthCheckResponseBuilder;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
@Health
@ApplicationScoped
public class ServiceHealthCheck implements HealthCheck {
@Inject
@ConfigProperty(name = "app.name")
private String app;
@Override
public HealthCheckResponse call() {
HealthCheckResponseBuilder responseBuilder = HealthCheckResponse.named(app);
responseBuilder.withData("memory", Runtime.getRuntime().freeMemory());
responseBuilder.withData("availableProcessors", Runtime.getRuntime().availableProcessors());
return responseBuilder.state(true).build();
}
}

View File

@ -0,0 +1 @@
app.name=bpe-qrcode

View File

@ -0,0 +1,10 @@
thorntail:
jaeger:
service-name: bpe-qrcode
sampler-type: const
sampler-parameter: 1
fluentd:
hostname: localhost
level: INFO
port: 24224
tag: bpe-qrcode

View File

@ -0,0 +1,7 @@
thorntail:
jaeger:
service-name: bpe-qrcode
sampler-type: const
sampler-parameter: 1
enable-b3-header-propagation: true
remote-reporter-http-endpoint: 'http://jaeger-collector.istio-system:14268/api/traces'

View File

@ -0,0 +1,84 @@
package test.rest;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.container.test.api.RunAsClient;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.arquillian.junit.InSequence;
import org.jboss.arquillian.test.api.ArquillianResource;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.asset.EmptyAsset;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.jboss.shrinkwrap.resolver.api.maven.Maven;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import javax.json.JsonObject;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.File;
import java.io.IOException;
import java.net.URL;
@RunWith(Arquillian.class)
public class QRCodeEndPointTest {
@ArquillianResource
private URL webappUrl;
WebTarget target;
ObjectMapper om = new ObjectMapper();
@Before
public void before() throws Exception {
target = ClientBuilder.newClient().target(webappUrl.toURI());
}
@Deployment
public static WebArchive createTestArchive() {
File[] files = Maven.resolver().loadPomFromFile("pom.xml")
.importRuntimeDependencies().resolve().withTransitivity().asFile();
WebArchive war = ShrinkWrap.create(WebArchive.class)
.addAsLibraries(files)
.addPackages(true, "br.com.trevezani.bpechave")
.addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml");
return war;
}
@Test
@RunAsClient
@InSequence(1)
public void testQRCode() throws IOException {
final Response response = target.path("qrcode")
.path("2")
.path("23")
.path("20190621")
.path("04406541659")
.path("63")
.path("001")
.path("1")
.path("13")
.path("123")
.request(MediaType.APPLICATION_JSON_TYPE)
.get();
Assert.assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
JsonObject obj = response.readEntity(JsonObject.class);
Assert.assertNotNull("QRCode inválido", obj);
System.out.println("Validando o retorno: ".concat(obj.toString()));
Assert.assertEquals("QRCode diferente: ".concat(obj.getString("qrcode")),
"https://dfe-portal.svrs.rs.gov.br/bpe/qrCode?chbpe=23196200004406541659630010000000131000001232&tpamb=2", obj.getString("qrcode"));
}
}

View File

@ -0,0 +1,16 @@
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: bpe-api
namespace: bpe
spec:
host: bpe-api
subsets:
- name: v10
labels:
version: v10
- name: v11
labels:
version: v11

View File

@ -0,0 +1,35 @@
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: bpe-gateway
namespace: bpe
spec:
selector:
istio: ingressgateway # use istio default controller
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: bpe
namespace: bpe
spec:
hosts:
- "*"
gateways:
- bpe-gateway
http:
- match:
- uri:
prefix: /api
route:
- destination:
host: bpe-api
port:
number: 8080

View File

@ -0,0 +1,9 @@
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: bpe-ingress
namespace: bpe
spec:
backend:
serviceName: bpe-api
servicePort: 8080

View File

@ -0,0 +1,20 @@
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: bpe-gateway
namespace: bpe
spec:
hosts:
- "*"
gateways:
- bpe-gateway
http:
- match:
- uri:
prefix: /api
route:
- destination:
host: bpe-api
subset: v11
port:
number: 8080

View File

@ -0,0 +1,27 @@
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: bpe-gateway
namespace: bpe
spec:
hosts:
- "*"
gateways:
- bpe-gateway
http:
- match:
- uri:
prefix: /api
route:
- destination:
host: bpe-api
subset: v10
port:
number: 8080
weight: 90
- destination:
host: bpe-api
subset: v11
port:
number: 8080
weight: 10

View File

@ -0,0 +1,19 @@
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: bpe-qrcode
namespace: bpe
spec:
host: bpe-qrcode
subsets:
- name: v11
labels:
version: v11
- name: v12
labels:
version: v12

View File

@ -0,0 +1,14 @@
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: bpe-qrcode
namespace: bpe
spec:
hosts:
- bpe-qrcode
http:
- route:
- destination:
host: bpe-qrcode
subset: v12
---

View File

@ -0,0 +1,19 @@
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: bpe-qrcode
namespace: bpe
spec:
hosts:
- bpe-qrcode
http:
- route:
- destination:
host: bpe-qrcode
subset: v11
weight: 90
- destination:
host: bpe-qrcode
subset: v12
weight: 10
---

View File

@ -0,0 +1,34 @@
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
labels:
app: bpe-api
version: 1.0.0
name: bpe-api-1.0.0
namespace: bpe
spec:
replicas: 1
selector:
matchLabels:
app: bpe-api
version: 1.0.0
template:
metadata:
labels:
app: bpe-api
version: 1.0.0
spec:
containers:
- env:
- name: JAVA_OPTIONS
value: -Xms15m -Xmx15m -Xmn15m
name: bpe-api
image: <local ip>:5000/bpe-api:1.0.0
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
name: http
protocol: TCP
restartPolicy: Always
imagePullSecrets:
- name: service-registry

View File

@ -0,0 +1,48 @@
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: bpe-api
version: v11
name: bpe-api-v11
namespace: bpe
spec:
replicas: 1
selector:
matchLabels:
app: bpe-api
version: v11
template:
metadata:
labels:
app: bpe-api
version: v11
annotations:
sidecar.istio.io/inject: "true"
spec:
containers:
- name: bpe-api
image: 192.168.1.9:5000/bpe-api:1.0.11
imagePullPolicy: IfNotPresent
env:
- name: JAVA_OPTIONS
value: -Xms15m -Xmx15m -Xmn15m
- name: ambiente
valueFrom:
configMapKeyRef:
name: bpe-config
key: ambiente
ports:
- containerPort: 8080
name: http
protocol: TCP
- containerPort: 8778
name: jolokia
protocol: TCP
- containerPort: 9779
name: prometheus
protocol: TCP
securityContext:
privileged: false
imagePullSecrets:
- name: service-registry

View File

@ -0,0 +1,14 @@
apiVersion: v1
kind: Service
metadata:
name: bpe-api
namespace: bpe
labels:
app: bpe-api
service: bpe-api
spec:
ports:
- name: http
port: 8080
selector:
app: bpe-api

View File

@ -0,0 +1,34 @@
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
labels:
app: bpe-chave
version: 1.0.0
name: bpe-chave-1.0.0
namespace: bpe
spec:
replicas: 1
selector:
matchLabels:
app: bpe-chave
version: 1.0.0
template:
metadata:
labels:
app: bpe-chave
version: 1.0.0
spec:
containers:
- env:
- name: JAVA_OPTIONS
value: -Xms15m -Xmx15m -Xmn15m
name: bpe-chave
image: <local ip>:5000/bpe-chave:1.0.0
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
name: http
protocol: TCP
restartPolicy: Always
imagePullSecrets:
- name: service-registry

View File

@ -0,0 +1,48 @@
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: bpe-chave
version: v11
name: bpe-chave-v11
namespace: bpe
spec:
replicas: 1
selector:
matchLabels:
app: bpe-chave
version: v11
template:
metadata:
labels:
app: bpe-chave
version: v11
annotations:
sidecar.istio.io/inject: "true"
spec:
containers:
- name: bpe-chave
image: 192.168.1.9:5000/bpe-chave:1.0.11
imagePullPolicy: IfNotPresent
env:
- name: JAVA_OPTIONS
value: -Xms15m -Xmx15m -Xmn15m
- name: ambiente
valueFrom:
configMapKeyRef:
name: bpe-config
key: ambiente
ports:
- containerPort: 8080
name: http
protocol: TCP
- containerPort: 8778
name: jolokia
protocol: TCP
- containerPort: 9779
name: prometheus
protocol: TCP
securityContext:
privileged: false
imagePullSecrets:
- name: service-registry

View File

@ -0,0 +1,13 @@
apiVersion: v1
kind: Service
metadata:
name: bpe-chave
namespace: bpe
labels:
app: bpe-chave
spec:
ports:
- name: http
port: 8080
selector:
app: bpe-chave

View File

@ -0,0 +1,34 @@
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
labels:
app: bpe-qrcode
version: 1.0.0
name: bpe-qrcode-1.0.0
namespace: bpe
spec:
replicas: 1
selector:
matchLabels:
app: bpe-qrcode
version: 1.0.0
template:
metadata:
labels:
app: bpe-qrcode
version: 1.0.0
spec:
containers:
- env:
- name: JAVA_OPTIONS
value: -Xms15m -Xmx15m -Xmn15m
name: bpe-qrcode
image: <local ip>:5000/bpe-qrcode:1.0.0
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
name: http
protocol: TCP
restartPolicy: Always
imagePullSecrets:
- name: service-registry

View File

@ -0,0 +1,48 @@
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: bpe-qrcode
version: v11
name: bpe-qrcode-v11
namespace: bpe
spec:
replicas: 1
selector:
matchLabels:
app: bpe-qrcode
version: v11
template:
metadata:
labels:
app: bpe-qrcode
version: v11
annotations:
sidecar.istio.io/inject: "true"
spec:
containers:
- name: bpe-qrcode
image: 192.168.1.9:5000/bpe-qrcode:1.0.11
imagePullPolicy: IfNotPresent
env:
- name: JAVA_OPTIONS
value: -Xms15m -Xmx15m -Xmn15m
- name: ambiente
valueFrom:
configMapKeyRef:
name: bpe-config
key: ambiente
ports:
- containerPort: 8080
name: http
protocol: TCP
- containerPort: 8778
name: jolokia
protocol: TCP
- containerPort: 9779
name: prometheus
protocol: TCP
securityContext:
privileged: false
imagePullSecrets:
- name: service-registry

View File

@ -0,0 +1,13 @@
apiVersion: v1
kind: Service
metadata:
name: bpe-qrcode
namespace: bpe
labels:
app: bpe-qrcode
spec:
ports:
- name: http
port: 8080
selector:
app: bpe-qrcode

View File

@ -0,0 +1,10 @@
{
"apiVersion": "v1",
"kind": "Namespace",
"metadata": {
"name": "bpe",
"labels": {
"name": "bpe"
}
}
}

View File

@ -0,0 +1,46 @@
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: elasticsearch
spec:
selector:
matchLabels:
component: elasticsearch
template:
metadata:
labels:
component: elasticsearch
spec:
containers:
- name: elasticsearch
image: docker.elastic.co/elasticsearch/elasticsearch:6.5.4
env:
- name: discovery.type
value: single-node
ports:
- containerPort: 9200
name: http
protocol: TCP
resources:
limits:
cpu: 500m
memory: 4Gi
requests:
cpu: 500m
memory: 4Gi
---
apiVersion: v1
kind: Service
metadata:
name: elasticsearch
labels:
service: elasticsearch
spec:
type: NodePort
selector:
component: elasticsearch
ports:
- port: 9200
targetPort: 9200

View File

@ -0,0 +1,54 @@
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
name: fluentd
namespace: kube-system
labels:
k8s-app: fluentd-logging
version: v1
kubernetes.io/cluster-service: "true"
spec:
template:
metadata:
labels:
k8s-app: fluentd-logging
version: v1
kubernetes.io/cluster-service: "true"
spec:
serviceAccount: fluentd
serviceAccountName: fluentd
tolerations:
- key: node-role.kubernetes.io/master
effect: NoSchedule
containers:
- name: fluentd
image: fluent/fluentd-kubernetes-daemonset:v1.3-debian-elasticsearch
env:
- name: FLUENT_ELASTICSEARCH_HOST
value: "elasticsearch.logging"
- name: FLUENT_ELASTICSEARCH_PORT
value: "9200"
- name: FLUENT_ELASTICSEARCH_SCHEME
value: "http"
- name: FLUENT_UID
value: "0"
resources:
limits:
memory: 200Mi
requests:
cpu: 100m
memory: 200Mi
volumeMounts:
- name: varlog
mountPath: /var/log
- name: varlibdockercontainers
mountPath: /var/lib/docker/containers
readOnly: true
terminationGracePeriodSeconds: 30
volumes:
- name: varlog
hostPath:
path: /var/log
- name: varlibdockercontainers
hostPath:
path: /var/lib/docker/containers

View File

@ -0,0 +1,38 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: fluentd
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
name: fluentd
namespace: kube-system
rules:
- apiGroups:
- ""
resources:
- pods
- namespaces
verbs:
- get
- list
- watch
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: fluentd
roleRef:
kind: ClusterRole
name: fluentd
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: ServiceAccount
name: fluentd
namespace: kube-system

View File

@ -0,0 +1,41 @@
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: kibana
spec:
selector:
matchLabels:
run: kibana
template:
metadata:
labels:
run: kibana
spec:
containers:
- name: kibana
image: docker.elastic.co/kibana/kibana:6.5.4
env:
- name: ELASTICSEARCH_URL
value: http://elasticsearch:9200
- name: XPACK_SECURITY_ENABLED
value: "true"
ports:
- containerPort: 5601
name: http
protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
name: kibana
labels:
service: kibana
spec:
type: NodePort
selector:
run: kibana
ports:
- port: 5601
targetPort: 5601

View File

@ -0,0 +1,39 @@
version: "3.7"
services:
agreggrator:
build: ./fluentd
ports:
- "24224:24224"
- "24224:24224/udp"
volumes:
- ./fluentd/fluent.conf:/fluentd/etc/fluent.conf
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:7.3.2
environment:
- discovery.type=single-node
- bootstrap.memory_lock=true
- "ES_JAVA_OPTS=-Xms1g -Xmx1g"
user: 'elasticsearch'
volumes:
- elasticsearch-data:/usr/share/elasticsearch/data
ulimits:
memlock:
soft: -1
hard: -1
nofile:
soft: 65536
hard: 65536
ports:
- "9200:9200"
kibana:
image: docker.elastic.co/kibana/kibana:7.3.2
links:
- elasticsearch
ports:
- "5601:5601"
environment:
- ELASTICSEARCH_HOSTS=http://elasticsearch:9200
depends_on:
- elasticsearch
volumes:
elasticsearch-data:

View File

@ -0,0 +1,18 @@
FROM fluent/fluentd:v1.5-1
# Use root account to use apk
USER root
RUN apk add --no-cache --update geoip-dev \
&& apk add --no-cache --update --virtual .build-deps build-base ruby-dev \
&& echo 'gem: --no-document' >> /etc/gemrc \
&& gem install fluent-plugin-elasticsearch fluent-plugin-woothee fluent-plugin-ua-parser fluent-plugin-geoip-filter fluent-plugin-multi-format-parser \
&& gem sources --clear-all \
&& apk del .build-deps \
&& rm -rf /tmp/* /var/tmp/* /usr/lib/ruby/gems/*/cache/*.gem
COPY fluent.conf /fluentd/etc/
COPY entrypoint.sh /bin/
ENV FLUENT_UID=0
#USER fluent

View File

@ -0,0 +1,28 @@
#!/bin/sh
#source vars if file exists
DEFAULT=/etc/default/fluentd
if [ -r $DEFAULT ]; then
set -o allexport
. $DEFAULT
set +o allexport
fi
# If the user has supplied only arguments append them to `fluentd` command
if [ "${1#-}" != "$1" ]; then
set -- fluentd "$@"
fi
# If user does not supply config file or plugins, use the default
if [ "$1" = "fluentd" ]; then
if ! echo $@ | grep ' \-c' ; then
set -- "$@" -c /fluentd/etc/${FLUENTD_CONF}
fi
if ! echo $@ | grep ' \-p' ; then
set -- "$@" -p /fluentd/plugins
fi
fi
exec "$@"

View File

@ -0,0 +1,55 @@
# fluentd/conf/fluent.conf
# <system>
# log_level ERROR
# </system>
<source>
@type forward
port 24224
bind 0.0.0.0
tag bpe
</source>
<filter *.**>
@type parser
# format /^(?<time>\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2},\d{3}) (?<log_level>\w+) \[(?<class>.*)\] \((?<pid>.*)\) (?<message>.*)/
key_name message
# time_format %Y-%m-%d %H:%M:%S,%L
<parse>
@type json
json_parser yajl
</parse>
</filter>
<match *.**>
@type copy
<store>
@type elasticsearch
host elasticsearch
port 9200
logstash_format true
logstash_prefix bpe
logstash_dateformat %Y%m%d
include_tag_key true
tag_key @log_name
flush_interval 1s
<buffer tag>
#@type memory # file #or memory
@type file
path /tmp/fluentd*.buffer
flush_mode interval
retry_type exponential_backoff
flush_thread_count 4
flush_interval 1s
retry_forever
retry_max_interval 30
chunk_limit_size 2M
queue_limit_length 8
overflow_action block
</buffer>
</store>
<store>
@type stdout
</store>
</match>

View File

@ -0,0 +1,135 @@
version: '3'
services:
jaeger:
image: jaegertracing/all-in-one:1.8
ports:
- "5775:5775/udp"
- "6831:6831/udp"
- "6832:6832/udp"
- "5778:5778"
- "16686:16686"
- "14268:14268"
- "9411:9411"
environment:
- COLLECTOR_ZIPKIN_HTTP_PORT=9411
networks:
mp-net:
ipv4_address: 172.18.0.5
agreggrator:
build: ./fluentd
ports:
- "24224:24224"
- "24224:24224/udp"
volumes:
- ./fluentd/fluent.conf:/fluentd/etc/fluent.conf
networks:
mp-net:
ipv4_address: 172.18.0.6
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:7.3.2
environment:
- discovery.type=single-node
- bootstrap.memory_lock=true
- "ES_JAVA_OPTS=-Xms1g -Xmx1g"
user: 'elasticsearch'
volumes:
- elasticsearch-data:/usr/share/elasticsearch/data
ulimits:
memlock:
soft: -1
hard: -1
nofile:
soft: 65536
hard: 65536
ports:
- "9200:9200"
networks:
mp-net:
ipv4_address: 172.18.0.7
kibana:
image: docker.elastic.co/kibana/kibana:7.3.2
links:
- elasticsearch
ports:
- "5601:5601"
environment:
- ELASTICSEARCH_HOSTS=http://elasticsearch:9200
depends_on:
- elasticsearch
networks:
mp-net:
ipv4_address: 172.18.0.8
mp-bpe-api:
image: bpe-api:1.0.10
ports:
- "8080:8080"
- "5010:5006"
depends_on:
- jaeger
networks:
mp-net:
ipv4_address: 172.18.0.11
links:
- jaeger
environment:
- bpeqrcode.api.url=http://mp-bpe-qrcode:8080
- bpechave.api.url=http://mp-bpe-chave:8080
- JAEGER_AGENT_HOST=jaeger
- JAEGER_SERVICE_NAME=bpe-api
- JAEGER_REPORTER_LOG_SPANS=true
- JAEGER_SAMPLER_TYPE=const
- JAEGER_SAMPLER_PARAM=1
- thorntail.fluentd.hostname=172.18.0.6
mp-bpe-qrcode:
image: bpe-qrcode:1.0.10
ports:
- "8081:8080"
- "5011:5006"
depends_on:
- jaeger
networks:
mp-net:
ipv4_address: 172.18.0.12
links:
- jaeger
environment:
- bpechave.api.url=http://mp-bpe-chave:8080
- JAEGER_AGENT_HOST=jaeger
- JAEGER_SERVICE_NAME=bpe-qrcode
- JAEGER_REPORTER_LOG_SPANS=true
- JAEGER_SAMPLER_TYPE=const
- JAEGER_SAMPLER_PARAM=1
- thorntail.fluentd.hostname=172.18.0.6
mp-bpe-chave:
image: bpe-chave:1.0.10
ports:
- "8082:8080"
- "5012:5006"
depends_on:
- jaeger
networks:
mp-net:
ipv4_address: 172.18.0.13
links:
- jaeger
environment:
- JAEGER_AGENT_HOST=jaeger
- JAEGER_SERVICE_NAME=bpe-chave
- JAEGER_REPORTER_LOG_SPANS=true
- JAEGER_SAMPLER_TYPE=const
- JAEGER_SAMPLER_PARAM=1
- thorntail.fluentd.hostname=172.18.0.6
volumes:
elasticsearch-data:
networks:
mp-net:
driver: bridge
ipam:
config:
- subnet: 172.18.0.0/16

View File

@ -0,0 +1,18 @@
FROM fluent/fluentd:v1.5-1
# Use root account to use apk
USER root
RUN apk add --no-cache --update geoip-dev \
&& apk add --no-cache --update --virtual .build-deps build-base ruby-dev \
&& echo 'gem: --no-document' >> /etc/gemrc \
&& gem install fluent-plugin-elasticsearch fluent-plugin-woothee fluent-plugin-ua-parser fluent-plugin-geoip-filter fluent-plugin-multi-format-parser \
&& gem sources --clear-all \
&& apk del .build-deps \
&& rm -rf /tmp/* /var/tmp/* /usr/lib/ruby/gems/*/cache/*.gem
COPY fluent.conf /fluentd/etc/
COPY entrypoint.sh /bin/
ENV FLUENT_UID=0
#USER fluent

View File

@ -0,0 +1,28 @@
#!/bin/sh
#source vars if file exists
DEFAULT=/etc/default/fluentd
if [ -r $DEFAULT ]; then
set -o allexport
. $DEFAULT
set +o allexport
fi
# If the user has supplied only arguments append them to `fluentd` command
if [ "${1#-}" != "$1" ]; then
set -- fluentd "$@"
fi
# If user does not supply config file or plugins, use the default
if [ "$1" = "fluentd" ]; then
if ! echo $@ | grep ' \-c' ; then
set -- "$@" -c /fluentd/etc/${FLUENTD_CONF}
fi
if ! echo $@ | grep ' \-p' ; then
set -- "$@" -p /fluentd/plugins
fi
fi
exec "$@"

View File

@ -0,0 +1,55 @@
# fluentd/conf/fluent.conf
# <system>
# log_level ERROR
# </system>
<source>
@type forward
port 24224
bind 0.0.0.0
tag bpe
</source>
<filter *.**>
@type parser
# format /^(?<time>\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2},\d{3}) (?<log_level>\w+) \[(?<class>.*)\] \((?<pid>.*)\) (?<message>.*)/
key_name message
# time_format %Y-%m-%d %H:%M:%S,%L
<parse>
@type json
json_parser yajl
</parse>
</filter>
<match *.**>
@type copy
<store>
@type elasticsearch
host elasticsearch
port 9200
logstash_format true
logstash_prefix bpe
logstash_dateformat %Y%m%d
include_tag_key true
tag_key @log_name
flush_interval 1s
<buffer tag>
#@type memory # file #or memory
@type file
path /tmp/fluentd*.buffer
flush_mode interval
retry_type exponential_backoff
flush_thread_count 4
flush_interval 1s
retry_forever
retry_max_interval 30
chunk_limit_size 2M
queue_limit_length 8
overflow_action block
</buffer>
</store>
<store>
@type stdout
</store>
</match>