From 2e022fb13dd075a09b2ae8fabc142aedddbcee6c Mon Sep 17 00:00:00 2001 From: Maksim Aniskov Date: Sat, 27 Jan 2024 17:59:30 +0100 Subject: [PATCH] Import second model for comparison --- README.md | 7 ++-- archi/entrypoint.sh | 19 ++++++++++- archixml2csv/Dockerfile | 5 ++- archixml2csv/wrapper.sh | 17 ++++++++++ compose.git.yaml | 23 ++++++------- compose.yaml | 10 +++--- neo4j/Dockerfile | 1 + neo4j/archi-verifier.sh | 5 +++ neo4j/import-archi-model.cypher | 20 +++++------ neo4j/import-archi-model2.cypher | 57 ++++++++++++++++++++++++++++++++ sqlite/wrapper.sh | 11 ++++++ 11 files changed, 141 insertions(+), 34 deletions(-) create mode 100755 archixml2csv/wrapper.sh create mode 100644 neo4j/import-archi-model2.cypher diff --git a/README.md b/README.md index 640db31..6229e06 100644 --- a/README.md +++ b/README.md @@ -242,7 +242,7 @@ Verification completed This is summary of command line syntax: ~~~ -docker compose run [-f compose.yaml [-f compose.ui.yaml] [-f compose.git.yaml]] [--service-ports] --rm sqlite|neo4j +docker compose [-f compose.yaml [-f compose.ui.yaml] [-f compose.git.yaml]] run [--service-ports] --rm sqlite|neo4j ~~~ There are four things you leverage to control how this solution behaves: @@ -274,11 +274,12 @@ In case you provide any of the non-default YAMLs, you need to include ```-f comp [-f compose.yaml [-f compose.ui.yaml] [-f compose.git.yaml] ] ``` -## Environmant variables +## Environment variables ```ARCHI_FOLDER``` Default value is ```.``` (current folder)
```ARCHI_FILE``` Default value is ```model.archimate``` -
The solution processes model file with this name you provide in this folder. +The solution processes model file with this name you provide in this folder. +
```ARCHI_FILE2``` (Optional) The second model for model comparison. ```SQLITE_SCRIPTS_FOLDER``` Default value is ```./verification_scripts_sql```
The solution runs SQL scripts it finds in this folder. diff --git a/archi/entrypoint.sh b/archi/entrypoint.sh index 4011e2a..8e519fe 100755 --- a/archi/entrypoint.sh +++ b/archi/entrypoint.sh @@ -1,4 +1,21 @@ #!/bin/sh export DISPLAY=:99 Xvfb $DISPLAY & -/opt/Archi/Archi -application com.archimatetool.commandline.app -consoleLog -nosplash $@ + +/opt/Archi/Archi -application com.archimatetool.commandline.app -consoleLog -nosplash \ + --modelrepository.cloneModel "${GIT_URL}" \ + --modelrepository.userName "${GIT_USER}" \ + --modelrepository.passFile "/usr/var/passwords/${GIT_PASSWORD_FILE}" \ + --modelrepository.loadModel /tmp/archi-model-clone \ + --saveModel /usr/var/intermediate_files/model.archimate + +rm -f /usr/var/intermediate_files/model2.archimate +if [ "$GIT_URL2" ] +then + /opt/Archi/Archi -application com.archimatetool.commandline.app -consoleLog -nosplash \ + --modelrepository.cloneModel "${GIT_URL2}" \ + --modelrepository.userName "${GIT_USER2}" \ + --modelrepository.passFile "/usr/var/passwords/${GIT_PASSWORD_FILE2}" \ + --modelrepository.loadModel /tmp/archi-model-clone \ + --saveModel /usr/var/intermediate_files/model2.archimate +fi diff --git a/archixml2csv/Dockerfile b/archixml2csv/Dockerfile index 804abe3..b43c32e 100644 --- a/archixml2csv/Dockerfile +++ b/archixml2csv/Dockerfile @@ -3,6 +3,5 @@ FROM python:3.11-slim RUN apt-get update && apt-get install -y unzip && rm -rf /var/lib/apt/lists/* COPY archixml2csv.py /usr/src/archixml2csv.py -CMD cp "${ARCHI_MODEL_FILE}" /tmp/archimate.model && \ - (cd /tmp && unzip -o archimate.model model.xml && mv model.xml archimate.model || true) && \ - python /usr/src/archixml2csv.py /tmp/archimate.model +COPY wrapper.sh wrapper.sh +ENTRYPOINT ["/wrapper.sh"] diff --git a/archixml2csv/wrapper.sh b/archixml2csv/wrapper.sh new file mode 100755 index 0000000..f3b1dc8 --- /dev/null +++ b/archixml2csv/wrapper.sh @@ -0,0 +1,17 @@ +#!/bin/sh + +set -e + +cp "${MODELS_FOLDER}/${ARCHI_FILE-model.archimate}" /tmp/archimate.model +(cd /tmp && unzip -o archimate.model model.xml && mv model.xml archimate.model || true) +python /usr/src/archixml2csv.py /tmp/archimate.model + +rm -fr model2 +if [ "$ARCHI_FILE2" ] && [ -f "${MODELS_FOLDER}/${ARCHI_FILE2}" ] +then + cp "${MODELS_FOLDER}/${ARCHI_FILE2}" /tmp/archimate2.model + (cd /tmp && unzip -o archimate2.model model2.xml && mv model2.xml archimate2.model || true) + mkdir -p model2 + cd model2 + python /usr/src/archixml2csv.py /tmp/archimate2.model +fi diff --git a/compose.git.yaml b/compose.git.yaml index bd41fd4..28a50e9 100644 --- a/compose.git.yaml +++ b/compose.git.yaml @@ -2,19 +2,15 @@ services: archi: build: - context: https://github.com/MaksimAniskov/archi-powertools-verifier.git#0.x:/archi + context: https://github.com/MaksimAniskov/archi-powertools-verifier.git#1.x:/archi platform: linux/amd64 - command: - - --modelrepository.cloneModel - - ${GIT_URL} - - --modelrepository.userName - - ${GIT_USER} - - --modelrepository.passFile - - /usr/var/passwords/${GIT_PASSWORD_FILE} - - --modelrepository.loadModel - - /tmp/archi-model-clone - - --saveModel - - /usr/var/intermediate_files/model.archimate + environment: + GIT_URL: + GIT_USER: + GIT_PASSWORD_FILE: + GIT_URL2: + GIT_USER2: + GIT_PASSWORD_FILE2: volumes: - ${GIT_PASSWORD_FILES_FOLDER-.}:/usr/var/passwords:ro - intermediate_files:/usr/var/intermediate_files @@ -24,6 +20,7 @@ services: archi: condition: service_completed_successfully environment: - ARCHI_MODEL_FILE: model.archimate + MODELS_FOLDER: /usr/var/intermediate_files + ARCHI_FILE2: model2.archimate volumes: - intermediate_files:/usr/var/intermediate_files diff --git a/compose.yaml b/compose.yaml index 6a2fc5f..024201a 100644 --- a/compose.yaml +++ b/compose.yaml @@ -2,9 +2,11 @@ services: archi2csv: build: - context: https://github.com/MaksimAniskov/archi-powertools-verifier.git#0.x:/archixml2csv + context: https://github.com/MaksimAniskov/archi-powertools-verifier.git#1.x:/archixml2csv environment: - ARCHI_MODEL_FILE: /usr/var/archimate_models/${ARCHI_FILE-model.archimate} + ARCHI_FILE: + ARCHI_FILE2: + MODELS_FOLDER: /usr/var/archimate_models working_dir: /usr/var/intermediate_files volumes: - ${ARCHI_FOLDER-.}:/usr/var/archimate_models:ro @@ -15,7 +17,7 @@ services: archi2csv: condition: service_completed_successfully build: - context: https://github.com/MaksimAniskov/archi-powertools-verifier.git#0.x:/neo4j + context: https://github.com/MaksimAniskov/archi-powertools-verifier.git#1.x:/neo4j volumes: - intermediate_files:/var/lib/neo4j/import/intermediate_files - ${NEO4J_SCRIPTS_FOLDER-./verification_scripts_cql}:/usr/var/verification_scripts:ro @@ -26,7 +28,7 @@ services: archi2csv: condition: service_completed_successfully build: - context: https://github.com/MaksimAniskov/archi-powertools-verifier.git#0.x:/sqlite + context: https://github.com/MaksimAniskov/archi-powertools-verifier.git#1.x:/sqlite volumes: - intermediate_files:/usr/var/intermediate_files - ${SQLITE_SCRIPTS_FOLDER-./verification_scripts_sql}:/usr/var/verification_scripts:ro diff --git a/neo4j/Dockerfile b/neo4j/Dockerfile index 6e055f4..b1785f2 100644 --- a/neo4j/Dockerfile +++ b/neo4j/Dockerfile @@ -6,5 +6,6 @@ ENV NEO4J_PLUGINS=[\"apoc\"] COPY archi-verifier.sh archi-verifier.sh COPY wrapper.sh wrapper.sh COPY import-archi-model.cypher import-archi-model.cypher +COPY import-archi-model2.cypher import-archi-model2.cypher ENTRYPOINT ["./wrapper.sh"] diff --git a/neo4j/archi-verifier.sh b/neo4j/archi-verifier.sh index 6cd9350..485592f 100755 --- a/neo4j/archi-verifier.sh +++ b/neo4j/archi-verifier.sh @@ -5,6 +5,11 @@ cp -r /usr/var/additional_data import/additional_data echo "Importing the Archimate model to Neo4j..." cypher-shell -f import-archi-model.cypher +if [ -f /var/lib/neo4j/import/intermediate_files/model2/elements.csv ] +then + echo "Importing the second Archimate model to Neo4j..." + cypher-shell -f import-archi-model2.cypher +fi echo "Executing verification scripts..." find import/verification_scripts -type f | sort | xargs -I {} sh -c 'echo "{}"; cypher-shell -f "{}"' diff --git a/neo4j/import-archi-model.cypher b/neo4j/import-archi-model.cypher index d48c626..8a3e422 100644 --- a/neo4j/import-archi-model.cypher +++ b/neo4j/import-archi-model.cypher @@ -10,16 +10,6 @@ MATCH (t:Element{archi_id:line.Target}) MERGE (s)-[:Relation{archi_id:line.ID, type:replace(line.Type,"Relationship",""), name:line.Name, specialization:line.Specialization}]->(t) RETURN count(*) AS `Imported relationships:`; -MATCH (n:Element) -CALL apoc.create.addLabels( id(n), [ n.type ] ) -YIELD node -REMOVE node.type; - -MATCH ()-[rel:Relation]->() -CALL apoc.refactor.setType(rel,rel.type) -YIELD input, output -REMOVE output.type; - LOAD CSV WITH HEADERS FROM "file:///intermediate_files/views.csv" AS line MERGE (:Archi_View{archi_id:line.ID, name:line.Name, documentation:line.Documentation}) RETURN count(*) AS `Imported views:`; @@ -57,3 +47,13 @@ MATCH ()-[r{archi_id:line.ID}]->() CALL apoc.create.setRelProperty(r, line.Key, line.Value) YIELD rel RETURN count(*) AS `Imported relationships' properties:`; + +MATCH (:Element)-[rel:Relation]->(:Element) +CALL apoc.refactor.setType(rel,rel.type) +YIELD input, output +REMOVE output.type; + +MATCH (n:Element) +CALL apoc.create.addLabels( id(n), [ n.type ] ) +YIELD node +REMOVE node.type; diff --git a/neo4j/import-archi-model2.cypher b/neo4j/import-archi-model2.cypher new file mode 100644 index 0000000..066f4a5 --- /dev/null +++ b/neo4j/import-archi-model2.cypher @@ -0,0 +1,57 @@ +LOAD CSV WITH HEADERS FROM "file:///intermediate_files/model2/elements.csv" AS line +MERGE (:Element{_archi_pwrt_verifier_model_n: 2, archi_id:line.ID, type:line.Type, name:line.Name, documentation:line.Documentation, specialization:line.Specialization}) +RETURN count(*) AS `Imported elements:`; + +LOAD CSV WITH HEADERS FROM "file:///intermediate_files/model2/relations.csv" AS line +MATCH (s:Element{_archi_pwrt_verifier_model_n: 2, archi_id:line.Source}) +MATCH (t:Element{_archi_pwrt_verifier_model_n: 2, archi_id:line.Target}) +MERGE (s)-[:Relation{_archi_pwrt_verifier_model_n: 2, archi_id:line.ID, type:replace(line.Type,"Relationship",""), name:line.Name, specialization:line.Specialization}]->(t) +RETURN count(*) AS `Imported relationships:`; + +LOAD CSV WITH HEADERS FROM "file:///intermediate_files/model2/views.csv" AS line +MERGE (:Archi_View{_archi_pwrt_verifier_model_n: 2, archi_id:line.ID, name:line.Name, documentation:line.Documentation}) +RETURN count(*) AS `Imported views:`; + +LOAD CSV WITH HEADERS FROM "file:///intermediate_files/model2/view-content.csv" AS line +MATCH (c:Element{_archi_pwrt_verifier_model_n: 2, archi_id:line.ObjectID}) +MATCH (v:Archi_View{_archi_pwrt_verifier_model_n: 2, archi_id:line.ViewID}) +MERGE (c)-[:Archi_PresentedIn]->(v) +RETURN count(*) AS `Imported elements and relationships in views:`; + +LOAD CSV WITH HEADERS FROM "file:///intermediate_files/model2/folders.csv" AS line +MERGE (:Archi_Folder{_archi_pwrt_verifier_model_n: 2, archi_id:line.ID, type:line.Type, name:line.Name,documentation:line.Documentation}) +RETURN count(*) AS `Imported folders:`; + +LOAD CSV WITH HEADERS FROM "file:///intermediate_files/model2/folders.csv" AS line +MATCH (f:Archi_Folder{_archi_pwrt_verifier_model_n: 2, archi_id:line.ID}) +MATCH (p:Archi_Folder{_archi_pwrt_verifier_model_n: 2, archi_id:line.Parent}) +MERGE (f)-[:Archi_SubfolderOf]->(p); + +// Problem: The following does not create relationship between a folder and Archi relation in the folder +LOAD CSV WITH HEADERS FROM "file:///intermediate_files/model2/folder-content.csv" AS line +MATCH (c:Element{_archi_pwrt_verifier_model_n: 2, archi_id:line.ObjectID}) +MATCH (f:Archi_Folder{_archi_pwrt_verifier_model_n: 2, archi_id:line.FolderID}) +MERGE (c)-[:Archi_LivesIn]->(f) +RETURN count(*) AS `Imported elements and relationships in folders:`; + +LOAD CSV WITH HEADERS FROM "file:///intermediate_files/model2/properties.csv" AS line +MATCH (n:Element{_archi_pwrt_verifier_model_n: 2, archi_id:line.ID}) +CALL apoc.create.setProperty(n, line.Key, line.Value) +YIELD node +RETURN count(*) AS `Imported elements' properties:`; + +LOAD CSV WITH HEADERS FROM "file:///intermediate_files/model2/properties.csv" AS line +MATCH ()-[r:Relation{_archi_pwrt_verifier_model_n: 2, archi_id:line.ID}]->() +CALL apoc.create.setRelProperty(r, line.Key, line.Value) +YIELD rel +RETURN count(*) AS `Imported relationships' properties:`; + +MATCH (:Element{_archi_pwrt_verifier_model_n: 2})-[rel:Relation{_archi_pwrt_verifier_model_n: 2}]->(:Element{_archi_pwrt_verifier_model_n: 2}) +CALL apoc.refactor.setType(rel,rel.type) +YIELD input, output +REMOVE output.type; + +MATCH (n:Element{_archi_pwrt_verifier_model_n: 2}) +CALL apoc.create.addLabels( id(n), [ n.type ] ) +YIELD node +REMOVE node.type; diff --git a/sqlite/wrapper.sh b/sqlite/wrapper.sh index f97ac46..360ce7f 100755 --- a/sqlite/wrapper.sh +++ b/sqlite/wrapper.sh @@ -8,6 +8,17 @@ sqlite3 -csv archi-exported.sqlite ".import /usr/var/intermediate_files/folder-c sqlite3 -csv archi-exported.sqlite ".import /usr/var/intermediate_files/views.csv views" sqlite3 -csv archi-exported.sqlite ".import /usr/var/intermediate_files/view-content.csv view_content" +if [ -f /usr/var/intermediate_files/model2/elements.csv ] +then + sqlite3 -csv archi-exported.sqlite ".import /usr/var/intermediate_files/model2/elements.csv model2_elements" + sqlite3 -csv archi-exported.sqlite ".import /usr/var/intermediate_files/model2/relations.csv model2_relations" + sqlite3 -csv archi-exported.sqlite ".import /usr/var/intermediate_files/model2/properties.csv model2_properties" + sqlite3 -csv archi-exported.sqlite ".import /usr/var/intermediate_files/model2/folders.csv model2_folders" + sqlite3 -csv archi-exported.sqlite ".import /usr/var/intermediate_files/model2/folder-content.csv model2_folder_content" + sqlite3 -csv archi-exported.sqlite ".import /usr/var/intermediate_files/model2/views.csv model2_views" + sqlite3 -csv archi-exported.sqlite ".import /usr/var/intermediate_files/model2/view-content.csv model2_view_content" +fi + echo "Executing verification scripts..." find /usr/var/verification_scripts -type f | sort | xargs -I {} sh -c 'echo "{}"; sqlite3 --init "{}" archi-exported.sqlite ""' echo "Verification completed"