Skip to content
/ LIME-EMR Public template

The distribution of OpenMRS 3 for MSF OCG

Notifications You must be signed in to change notification settings

MSF-OCG/LIME-EMR

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

74 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

MSF LIME EMR

Using Ozone Approach

Configuration hierarchy and inheritance

Assumptions

  • There are 3 levels of configurations: Distro < Country < Site
  • The default ineritance logic is for lower levels to overwrite above ones
  • Configurations includes backend and frontend binaries, frontend configs, initializer metadata, and assets like logos.
  • It primarly support OpenMRS, but aims to be flexible and also support Senaite, Superset, OpenFN, FHIR, etc.

Hierarchy overview - example

── pom.xml - Aggredator / Orchestrator  
      └── /distro/pom.xml - Organizational-wide Config  
      └── /countries - Country-specific Config  
            └── /iraq/pom.xl
      └── /sites - Site-specific Config  
            └── /mosul/pom.xl

Workflow diagram

%%{init: {'theme':'forest'}}%%
flowchart TD

subgraph Z["Github Repository 'LIME EMR'"]
direction LR
  A[Configuration in Github repository] -->|Release of Distro config| B[Build in Github Actions]
      A -->|Release of a Country config| B
      A -->|Release of a Site config| B
      A -->|Release of an Environment config| B
  B --> |Generate a Distro artefact| C[Artefact Repository in Github]
      B --> |Generate a Country artefact| C
      B --> |Generate a Site artefact| C
end

subgraph ZA["Execution Server"]
direction LR
      D[Running the LIME EMR]
end

Z --> |Pulling the artefacts| ZA
Loading

Example for configs for hierarchy demo of v1 - Week of April 8

Ozone Level OpenMRS RefApp

MSF Distro LIME EMR repository

Country level: Iraq

Site level: Mosul

Quick Start

Build

./scripts/mvnw clean package

Running MSF Distro

source distro/target/go-to-scripts-dir.sh
./start-demo.sh

Running MSF Iraq

cd countries/iraq/target/ozone-msf-iraq-<version>/run/docker/scripts
./start-demo.sh

Running MSF Mosul

cd sites/mosul/target/ozone-msf-mosul-<version>/run/docker/scripts
./start-demo.sh

Testing

  1. Install prerequisites brew install jq

  2. Clone EMR Tooling

  3. Update install directory

    INSTALL_DIR="**.**/home/lime/$APP_NAME"
  4. Disable logging in lime_emr.sh (success and error) Function to log success messages

log_success() {
    echo "[$(date +'%Y-%m-%dT%H:%M:%S%z')] Success: $1" # >> "$SUCCESS_LOG"
}

Comment out Function to log error messages

log_error() {
    echo "[$(date +'%Y-%m-%dT%H:%M:%S%z')] Error: $1" # >> "$ERROR_LOG"
}
  1. Comment out download_msf_artefact() function
   # curl -L -o "$download_name.zip" -H "$GITHUB_REQUEST_TYPE" -H "$GITHUB_AUTH_HEADER" -H "$GITHUB_API_VERSION" "$download_url" && log_success "Downloaded MSF Distro for the '$artifact_branch' branch." || log_error "Failed to download MSF Distro for the '$artifact_branch' branch."
  1. Remove docker and package installation if needed

  2. Run installation script chmod +x ./Procedures/lime_emr.sh sh ./Procedures/lime_emr.sh install mosul

Roadmap

  • In pom files, implement a merge logic for frontend config JSONs at the site level. It will merge frontend configs from the Distro, Country, and Site level together. The lower level will always overwrite the above level in case of conflicts. Example: externalRefLinks for the esm-primary-navigation-app
  • In pom files, replicate a similar logic for initializer configuration files - assumung that the lower level also always overwrite the above one.
  • Simplify the results of the build currently generating muliple targets for all levels, rather than a single one for the execution level, being the Site level. Example: ozone-msf-mosul-1.0.0-SNAPSHOT
  • Ensure that the Github Action build is running the right level of configs upon release or manual trigger - not triggering all of them aspecially for performance savings pursposes: Screenshot 2024-04-18 at 1 30 07 PM

Configurations are pulled from parent level, modified as necessary in the current level and then applied. Modifiication of configuration at the cuurent level involves either the exclusion of non-needed configuration and/or inclusion of configuration that are specific at the current level. This process maintains inheritance from parent level to child level while facilitating easy customization and maintains consistency across levels.

We use the maven's pom.xml file at the root of each level to define what configuration should be applied. We embrace maven's maven resources plugin to exclude/filter and include configs as different execution processes using the copy-resources goal. This allows us to add or remove files while copying them form the parent level to the current level's build directory after the parent's download.

  • <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-resources-plugin</artifactId>
        <executions>
            <!-- add executions to filter or add a file -->
        </executions>
    </plugin> 
  • <plugin>
        <artifactId>maven-resources-plugin</artifactId>
        ...
        <execution>
            <id>Exclude unneeded Ozone files</id>
            <phase>process-resources</phase>
            <goals>
                <goal>copy-resources</goal>
            </goals>
            <configuration>
                <outputDirectory>
                    <!-- destination of the file to copy-->
                    ${project.build.directory}/${project.artifactId}-${project.version}
                </outputDirectory> 
                <overwrite>true</overwrite>
                <resources>
                <resource>
                    <directory>${project.build.directory}/ozone</directory> <!-- source of the file to copy -->
                    <excludes>
                    <!-- exclude unneeded files here like: <exclude>distro/configs/**/ampathforms/*.*</exclude> -->
                    </excludes>
                </resource>
                </resources>
            </configuration>
        </execution>
        ...
    </plugin> 
  • <plugin>
        <artifactId>maven-resources-plugin</artifactId>
        ...
        <execution>
            <id>Copy MSF Disto docker compose .txt file</id>
            <phase>prepare-package</phase>
            <goals>
                <goal>copy-resources</goal>
            </goals>
            <configuration>
                <outputDirectory>
                    <!-- destination of the file to copy-->
                    ${project.build.directory}/${project.artifactId}-${project.version}/run/docker/scripts
                </outputDirectory> 
                <overwrite>true</overwrite>
                <resources>
                <resource>
                    <directory>${project.basedir}/../scripts</directory> <!-- source of the file to copy-->
                    <includes>
                    <!-- add more needed files here like: <include> docker-compose-files.txt</include> -->
                    </includes>
                </resource>
                </resources>
            </configuration>
        </execution>
        ...
    </plugin> 

    At the current level, metadata is loaded through the Initializer module. A CSV file is added to the configs/openmrs/initializer_config folder at the current level and if the parent level defines the same .csv file, the corresponding file is excluded like showed below. Read more about the initializer configuration here.

    Example

    Screenshot 2024-04-18 at 1 30 07 PM

MSF configuration are loaded using the msf-frontend-config.json We use the Apache Maven AntRun Plugin to execute a task that replaces the ozone configuration file in the .env file that docker compose uses while building the frontend. The .env file is located in the target/run/docker/.env at the current level.

Below is how its done

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-antrun-plugin</artifactId>
    <executions>
        <execution>
        <id>Add MSF-OCG LIME Frontend Configuration to ozone</id>
        <phase>process-resources</phase>
        <goals>
            <goal>run</goal>
        </goals>
        <configuration>
            <target>
            <echo message="Adding msf frontend config"/>
            <replaceregexp 
                file="${project.build.directory}/${project.artifactId}-${project.version}/run/docker/.env"
                match="ozone-frontend-config.json"
                replace="msf-frontend-config.json"
            />
            </target>
        </configuration>
        </execution>
    </executions>
</plugin>

This task replaces all the occurrences of the sting ozone-frontend-config.json with msf-frontend-config.json After building the project using maven, the SPA_CONFIG_URLS variable (it specifies the location of the frontend config file inside docker) in the .env file will have a value of /openmrs/spa/ozone/msf-frontend-config.json

Note: Docker compose will only load the file passed to the SPA_CONFIG_URLS in the .env file. This means that any other file present in the target but not added to the SPA_CONFIG_URLS will be ignored.

The OpenMRS frontend tooling supports loading a frontend configuration on top of the currently loaded configuration. This means that we can use one file to load general frontend configuration like at Organization level branding and logos, and at site level, an obs-table on top of the patient chart. Both these configuration will be loaded successfully.

We can also use the child frontend configuration file to override the inherited frontend configuration. This implies that each level should have its own frontend configuration file in case it needs to load new frontend configuration.

Examples

  • At organization level in pom.xml file

    <replaceregexp
        file="${project.build.directory}/${project.artifactId}-${project.version}/run/docker/.env"
        match="ozone-frontend-config.json" 
        replace="msf-frontend-config.json"
    />

    result to the .env file after build

    SPA_CONFIG_URLS=/openmrs/spa/ozone/msf-frontend-config.json
  • Site frontend configuration inheriting from Organization level in pom.xml file

    <replaceregexp 
        file="${project.build.directory}/${project.artifactId}-${project.version}/run/docker/.env"
        match="(SPA_CONFIG_URLS=.+)"
        replace="\1,/openmrs/spa/ozone/msf-mosul-frontend-config.json"
    />

    result to the .env file after build

    SPA_CONFIG_URLS=/openmrs/spa/ozone/msf-frontend-config.json, /openmrs/spa/ozone/msf-mosul-frontend-config-json

Release Notes

1.0.0-SNAPSHOT (in progress)