Skip to content
Snippets Groups Projects
Commit 22058fa2 authored by Benguria Elguezabal, Gorka's avatar Benguria Elguezabal, Gorka
Browse files

public release

parents
No related branches found
No related tags found
No related merge requests found
.git/
/target
*.bkp
stages:
- build_and_push
- redeploy
build_and_push:
image: docker/compose:latest
stage: build_and_push
services:
- docker:dind
script:
- docker build -t fokus_ujmt . --tag 094360380/wp4-user-journey-modeling-tool:be
- docker login docker.io -u "$DOCKER_REGISTRY_USER" -p "$DOCKER_REGISTRY_PASSWORD"
- docker push 094360380/wp4-user-journey-modeling-tool:be
tags:
- docker
only:
- kubernetes
redeploy_at_k8s:
image: alpine/k8s:1.21.5
stage: redeploy
script:
- kubectl config set-cluster local --server="${K8S_SERVER}"
- kubectl config set clusters.local.certificate-authority-data "${K8S_CERTIFICATE_AUTHORITY_DATA}"
- kubectl config set-credentials local --token="${K8S_USER_TOKEN}"
- kubectl config set-context local --cluster=local --user=local
- kubectl config use-context local
- kubectl --insecure-skip-tls-verify version
- kubectl get deployments ujmt-be -n ujmt-dev --insecure-skip-tls-verify
- kubectl rollout restart deployment ujmt-be -n ujmt-dev --insecure-skip-tls-verify
tags:
- docker
only:
- kubernetes
when: manual
This diff is collapsed.
[package]
name = "ujmtbackend"
version = "0.1.0"
authors = ["aop <anna.opaska@fokus.fraunhofer.de>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
clap = "4.0"
chrono = "0.4"
failure = "0.1"
uuid = { version = "1.4", features = ["serde", "v4", "fast-rng", "macro-diagnostics"]}
slog = "2.7"
slog-async = "2.7"
slog-term = "2.9"
slog-scope = "4.4"
slog-envlogger = "2.2"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
serde-xml-rs = "0.6"
yaserde = "0.8"
yaserde_derive = "0.8"
tokio = { version = "1.23", features = ["full"] }
tokio-postgres = { version = "0.7.8", features = ["with-uuid-1", "with-uuid-0_8"] }
warp = "0.3"
hyper = "0.14"
reqwest = { version = "0.11", features = ["json", "multipart"]}
http = "0.2"
\ No newline at end of file
FROM clux/muslrust:stable as build-env
RUN rustc --version
WORKDIR /app
COPY ./ .
RUN cargo build --release
RUN cp target/x86_64-unknown-linux-musl/release/ujmtbackend .
FROM alpine:latest AS finalize
RUN apk update && \
apk add upx
WORKDIR /app
COPY --from=build-env /app/ujmtbackend /app
RUN upx ujmtbackend
FROM alpine:latest as base
RUN apk add upx && apk add make && apk add git && apk add curl && apk add bash
RUN curl --proto '=https' --tlsv1.2 -sSf https://just.systems/install.sh | bash -s -- --to /usr/bin
RUN apk update && \
apk add ca-certificates && \
update-ca-certificates && \
rm -rf /var/cache/apk/* && \
addgroup app && \
adduser -G app -D app
# build an image
FROM scratch
COPY --from=base /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=base /etc/passwd /etc/passwd
COPY --from=base /etc/group /etc/group
COPY --from=base /lib/libssl.so.3 /lib/libssl.so.3
COPY --from=base /usr/lib/libssl.so.3 /usr/lib/libssl.so.3
WORKDIR /app
COPY --from=finalize /app/ujmtbackend /app
USER app:app
EXPOSE 8080
CMD ["/app/ujmtbackend","serve"]
# UJMT Backend
This is the backend of the User Journey Modeling Tool (UJMT).
[[_TOC_]]
## Purpose
1. receive user journey models from frontend
2. convert to BPMN
3. send BPMN to service engine
## Technicalities
| thing | content |
|---|---|
| Contact | Anna Opaska |
| Language | Rust |
## CI/CD
### dockerhub
Repository
- <https://hub.docker.com/repository/docker/094360380/wp4-user-journey-modeling-tool>
Tags
- wp4-user-journey-modeling-tool:fe
- wp4-user-journey-modeling-tool:pr
- wp4-user-journey-modeling-tool:be
## Local Development
### Testing
Test the BPMN generation with
~~~ shell
cargo run generate generate_example.json
~~~
Start the generator as a service (at localhost:8080) with
~~~ shell
cargo run serve
~~~
In the directory ujmtbackend, request the generator with
~~~ shell
curl http://localhost:8080/generate -d "@serve_example.json" -H "Content-Type: application/json"
~~~
[
{
"name": "Search for universities",
"service_id": "search_1"
},
{
"name": "Apply for funding",
"service_id": "funding_1"
},
{
"name": "Apply at university",
"service_id": "application_1"
}
]
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?><definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:g="http://www.jboss.org/drools/flow/gpd" xmlns:java="http://www.java.com/javaTypes" xmlns:tns="http://www.jboss.org/drools" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.jboss.org/drools" xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd http://www.jboss.org/drools drools.xsd http://www.bpsim.org/schemas/1.0 bpsim.xsd" id="Definition" exporter="org.eclipse.bpmn2.modeler.core" exporterVersion="1.4.2.Final-v20171109-1930-B1"><process id="def_process" name="Default Process" isExecutable="true" xmlns:tns="http://www.jboss.org/drools" tns:packageName="defaultPackage" processType="Private"><startEvent id="def_start_event" name="Default Start Event"><extensionElements><tns:metaData name="elementname"><tns:metaValue>Default Start Event</tns:metaValue></tns:metaData></extensionElements></startEvent><endEvent id="def_end_event" name="Default End Event"><extensionElements><tns:metaData name="elementname"><tns:metaValue>Default End Event</tns:metaValue></tns:metaData></extensionElements></endEvent><serviceTask id="service_task_search_1" name="Search for universities"><documentation>serviceId:search_1</documentation></serviceTask><serviceTask id="service_task_funding_1" name="Apply for funding"><documentation>serviceId:funding_1</documentation></serviceTask><serviceTask id="service_task_application_1" name="Apply at university"><documentation>serviceId:application_1</documentation></serviceTask><sequenceFlow id="sequence_flow_search_1" sourceRef="def_start_event" targetRef="service_task_search_1" /><sequenceFlow id="sequence_flow_funding_1" sourceRef="service_task_search_1" targetRef="service_task_funding_1" /><sequenceFlow id="sequence_flow_application_1" sourceRef="service_task_funding_1" targetRef="service_task_application_1" /><sequenceFlow id="sequence_flow_def_end_event" sourceRef="service_task_application_1" targetRef="def_end_event" /></process><bpmndi:BPMNDiagram id="BPMNDiagram_def_process"><bpmndi:BPMNPlane bpmnElement="def_process" id="BPMNPlane_def_process"><bpmndi:BPMNShape bpmnElement="def_start_event" id="BPMNShape_def_start_event"><omgdc:Bounds height="36.0" width="36.0" x="0" y="0" /></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="service_task_search_1" id="BPMNShape_service_task_search_1"><omgdc:Bounds height="65.0" width="127.0" x="93" y="-14.0" /></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="service_task_funding_1" id="BPMNShape_service_task_funding_1"><omgdc:Bounds height="65.0" width="127.0" x="277" y="-14.0" /></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="service_task_application_1" id="BPMNShape_service_task_application_1"><omgdc:Bounds height="65.0" width="127.0" x="461" y="-14.0" /></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="def_end_event" id="BPMNShape_def_end_event"><omgdc:Bounds height="36.0" width="36.0" x="645" y="0" /></bpmndi:BPMNShape><bpmndi:BPMNEdge bpmnElement="sequence_flow_search_1" id="BPMNEdge_sequence_flow_search_1"><omgdi:waypoint x="36" y="18" /><omgdi:waypoint x="93" y="18" /></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="sequence_flow_funding_1" id="BPMNEdge_sequence_flow_funding_1"><omgdi:waypoint x="220" y="18" /><omgdi:waypoint x="277" y="18" /></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="sequence_flow_application_1" id="BPMNEdge_sequence_flow_application_1"><omgdi:waypoint x="404" y="18" /><omgdi:waypoint x="461" y="18" /></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="sequence_flow_def_end_event" id="BPMNEdge_sequence_flow_def_end_event"><omgdi:waypoint x="588" y="18" /><omgdi:waypoint x="645" y="18" /></bpmndi:BPMNEdge></bpmndi:BPMNPlane></bpmndi:BPMNDiagram></definitions>
\ No newline at end of file
generated_bpmn.png

53.2 KiB

{
"origin_country": "GERMANY",
"destination_country": "GREECE",
"workflow_type": "study",
"workflow_content": [
{
"name": "Search for universities",
"service_id": "search_1"
},
{
"name": "Apply for funding",
"service_id": "funding_1"
},
{
"name": "Apply at university",
"service_id": "application_1"
}
]
}
\ No newline at end of file
use crate::presenter;
use super::{UJMTError, read};
use clap::{Arg, Command, ArgMatches, ArgAction};
pub fn init() -> Command {
Command::new("generate_bpmn")
.about("Generate a BPMN file from a Drawio XML file")
.arg(
Arg::new("file")
.help("Drawio XML file")
.action(ArgAction::Set)
)
.arg(
Arg::new("out_dir")
.short('o')
.default_value(".")
.help("output directory")
.action(ArgAction::Set),
)
}
pub fn exec(args: &ArgMatches) -> Result<(), UJMTError> {
info!("Execute Generate");
let file = args.get_one::<String>("file").unwrap();
let result = read(file).map_err(|error| UJMTError::FileInputError(error))?;
let out_dir = args.get_one::<String>("out_dir").unwrap();
debug!("Use File: \"{}\"", file);
debug!("Use Output Directory: \"{}\"", out_dir);
if file.ends_with(".drawio") || file.ends_with(".xml")
{
generate_from_xml(result, file, out_dir)
.map_err(|error| UJMTError::GenerationFailed(error))?;
}
Ok(())
}
fn generate_from_xml(text: String, out_dir: &str, out_file: &str) -> Result<(), presenter::PresenterError> {
presenter::to_bpmn_from_xml(text, out_dir, out_file)
}
\ No newline at end of file
use crate::presenter;
use super::{UJMTError, read};
use clap::{Arg, Command, ArgMatches, ArgAction};
pub fn init() -> Command {
Command::new("generate_json")
.about("Generate a JSON file from a Drawio XML file")
.arg(
Arg::new("file")
.help("Drawio XML file")
.action(ArgAction::Set)
)
.arg(
Arg::new("out_dir")
.short('o')
.default_value(".")
.help("output directory")
.action(ArgAction::Set),
)
}
pub fn exec(args: &ArgMatches) -> Result<(), UJMTError> {
info!("Execute Generate");
let file = args.get_one::<String>("file").unwrap();
let result = read(file).map_err(|error| UJMTError::FileInputError(error))?;
let out_dir = args.get_one::<String>("out_dir").unwrap();
debug!("Use File: \"{}\"", file);
debug!("Use Output Directory: \"{}\"", out_dir);
if file.ends_with(".drawio") || file.ends_with(".xml")
{
generate_from_xml(result, file, out_dir)
.map_err(|error| UJMTError::GenerationFailed(error))?;
}
Ok(())
}
fn generate_from_xml(text: String, out_dir: &str, out_file: &str) -> Result<(), presenter::PresenterError> {
presenter::to_json_from_xml(text, out_dir, out_file)
}
\ No newline at end of file
use crate::presenter;
use clap::Command;
use failure::Fail;
use std::fs;
use std::io::{Read, stdin};
use std::path::Path;
//pub mod generate_bpmn;
pub mod generate_json;
pub mod serve;
pub mod validate;
pub mod version;
#[derive(Fail, Debug)]
pub enum UJMTError {
#[fail(display = "{}", _0)]
FileInputError(FileInputError),
#[fail(display = "BPMN File could not be generated. ({})", _0)]
GenerationFailed(presenter::PresenterError),
#[fail(display = "Service could not be started. ({})", _0)]
ServeFailed(Box<dyn std::error::Error + Send + Sync>),
#[fail(display = "Version could not be printed. ({})", _0)]
VersionError(std::io::Error),
#[fail(display = "An Error Occured. ({})", _0)]
Error(String),
}
#[derive(Fail, Debug)]
pub enum FileInputError {
#[fail(display = "File \"{}\" cannot be read. ({})", _0, _1)]
FileUnreadable(String, std::io::Error),
#[fail(display = "File \"{}\" does not exist.", _0)]
FileNotFound(String)
}
pub fn exec(app: &mut Command) {
let matches = app.clone().get_matches();
// initialise logger
let mut log_level = "info";
if matches.get_flag("debugging") {
log_level = "debug";
};
let _guard = slog_scope::set_global_logger(crate::core::log::new(log_level));
debug!("Initialised Global Logger");
let res;
// exec command or print help
match matches.subcommand() {
//Some(("generate_bpmn", submatches)) => res = generate_bpmn::exec(submatches),
Some(("generate_json", submatches)) => res = generate_json::exec(submatches),
Some(("serve", submatches)) => res = serve::exec(submatches),
Some(("validate", submatches)) => res = validate::exec(submatches),
Some(("version", submatches)) => res = version::exec(submatches),
_ =>
{
app.print_help().unwrap();
res = Ok(())
}
}
if res.is_err(){
error!("{}", res.unwrap_err());
}
}
fn read(input_file: &str) -> Result<String, FileInputError> {
let mut source = String::new();
if input_file == "" {
stdin()
.read_to_string(&mut source)
.map_err(|error| FileInputError::FileUnreadable(String::from("stdin"), error))?;
} else if Path::new(input_file).exists() {
source = fs::read_to_string(input_file)
.map_err(|error| FileInputError::FileUnreadable(input_file.to_string(), error))?;
} else {
return Err(FileInputError::FileNotFound(input_file.to_string()));
}
return Ok(source);
}
\ No newline at end of file
This diff is collapsed.
use crate::domain::usecases;
use super::{UJMTError, read};
use clap::{Arg, Command, ArgMatches, ArgAction};
pub fn init() -> Command {
Command::new("validate")
.about("Validate Drawio XML file for BPMN generation")
.arg(
Arg::new("file")
.help("Drawio XML file")
.action(ArgAction::Set)
)
}
pub fn exec(args: &ArgMatches) -> Result<(), UJMTError> {
info!("Execute Validate");
let file = args.get_one::<String>("file").unwrap();
let result = read(file).map_err(|error| UJMTError::FileInputError(error))?;
debug!("Use File: \"{}\"", file);
if validate_xml(result).is_ok() {
Ok(())
} else {
Err(UJMTError::Error("Validation failed".to_string()))
}
}
/*fn generate_from_json(text: String, out_dir: &str, out_file: &str) -> Result<(), presenter::PresenterError> {
presenter::to_bpmn_from_json(text, out_dir, out_file)
}*/
fn validate_xml(text: String) -> Result<(), usecases::UseCaseExecError> {
let mark_response = usecases::generate_mark_response_from_drawio(text.clone())?;
//let message = warp::reply::json(&mark_response);
info!("{:?}", mark_response);
//let message = warp::reply::json(&mark_response);
let json_string = serde_json::to_string(&mark_response);
if json_string.is_ok() {
info!("{:?}", json_string.unwrap());
}
Ok(())
}
\ No newline at end of file
use crate::cli::UJMTError;
use crate::core::config;
use clap::{Command, ArgMatches};
pub fn init() -> clap::Command {
Command::new("version").about("Prints version number")
}
pub fn exec(_matches: &ArgMatches) -> Result<(), UJMTError> {
println!("{} Version {}", config::SERVICE, config::VERSION);
Ok(())
}
\ No newline at end of file
pub const VERSION:&str = "0.2";
pub const SERVICE:&str = "UJMT.B";
pub const DEFAULT_PORT:&str = "8080";
pub const ENGINE_URL:&str = "https://ujse-ujse-dev.k8s.across-h2020.eu/across/1.0/workflowManagement";
pub const DATABASE_URL:&str = "postgresql://root@10.245.104.187:26257/defaultdb?sslmode=disable";
pub const FRONTEND_URL:&str = "http://localhost:8080";
\ No newline at end of file
extern crate slog_term;
extern crate slog_async;
use slog::Drain;
use uuid::Uuid;
use slog_envlogger;
pub fn new(log_level: &str) -> slog::Logger {
std::env::set_var("RUST_LOG", "info");
let _guard = slog_envlogger::init();
let decorator = slog_term::TermDecorator::new().build();
let drain = slog_term::FullFormat::new(decorator).build().fuse();
let drain = match log_level {
"debug" => drain.filter_level(slog::Level::Debug).fuse(),
_ => drain.filter_level(slog::Level::Info).fuse(),
};
let drain = slog_async::Async::new(drain).chan_size(1024).build().fuse();
let service_id = Uuid::new_v4().to_string();
let logger = slog::Logger::root(drain, o!("sid" => service_id));
return logger;
}
/*
pub fn new_file(log_level: &str, file: &str) -> slog::Logger {
}
pub fn new_term(log_level: &str) -> slog::Logger {
}*/
\ No newline at end of file
pub mod config;
pub mod log;
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment