Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 2 additions & 14 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ WORKDIR ${BASE_DIR}/build
USER ${USER}

# The dockerfile-build Maven profile excludes certain api integration tests that require access to the Docker service.
RUN mvn clean package -P dockerfile-build
RUN mvn clean install -P dockerfile-build

######################
### PACKAGING IMAGE ##
Expand All @@ -65,16 +65,4 @@ ADD ./docker/ /${BASE_DIR}/

EXPOSE 8080

CMD ["sh", "-c", "java \
-Dspring.profiles.active=${ENVIRONMENT} \
-Dapp.baseDomain=${BASE_DOMAIN} \
-Dredis.uri=${REDIS_URI} \
-Ddb.uri=${DB_URI} \
-Des.uri=${ELASTICSEARCH_URI} \
-Dokta.oauth2.issuer=${OAUTH_ISSUER} \
-Dokta.oauth2.clientId=${OAUTH_CLIENTID} \
-Dokta.oauth2.clientSecret=${OAUTH_CLIENTSECRET} \
-Dokta.oauth2.audience=${OAUTH_AUDIENCE} \
-Dspring.flyway.enabled=${MIGRATIONS_ENABLED} \
-jar ${BASE_DIR}/bin/osmt.jar"]

ENTRYPOINT ["/opt/osmt/bin/docker_entrypoint.sh"]
56 changes: 25 additions & 31 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# WGU Open Skills Management Toolset (OSMT)

## Overview
The Open Skills Management Tool (OSMT, pronounced "oz-mit") is a free, open-source instrument to facilitate the production of Rich Skill Descriptor (RSD) based open skills libraries. In short, it helps to create a commons skills language by creating, managing, and organizing skills-related data. An open-source framework allows everyone to use the tool collaboratively to define the RSD, so that those skills are translatable and transferable across educational institutions and hiring organizations within programs, curricula, and job descriptions.
The Open Skills Management Tool (OSMT, pronounced "oz-mit") is a free, open-source instrument to facilitate the production of Rich Skill Descriptor (RSD) based open skills libraries. In short, it helps to create a common skills language by creating, managing, and organizing skills-related data. An open-source framework allows everyone to use the tool collaboratively to define the RSD, so that those skills are translatable and transferable across educational institutions and hiring organizations within programs, curricula, and job descriptions.

## Architecture
OSMT is written in Kotlin with Spring Boot, and Angular. It uses backend-instances of MySQL, Redis, and Elastisearch.
Expand All @@ -19,51 +19,37 @@ OSMT requires certain software and SDKs to build:
* Maven uses an embedded copy of Node v10.16.0 and npm 6.10.2 (see [About frontend-maven-plugin](./ui/README.md#about-frontend-maven-plugin) in the UI README file).
* Locally, a developer probably has their own versions of NodeJS and npm installed. They should be >= the versions given above.
* a recent version of Docker and docker-compose
* Recommended 4 GB Memory
* Recommended 4 GB memory allocated to the Docker service

### Project Structure
OSMT is a multi-module Maven project. pom.xml files exist in the project root, `./api` and `./ui` directories. Running the command `mvn clean package` from the project root will create a fat jar in the target directory that contains both the backend server and the prod-built Angular frontend static files.
OSMT is a multi-module Maven project. pom.xml files exist in the project root, `./api` and `./ui` directories. Running the command `mvn clean install` from the project root will create a fat jar in the target directory that contains both the backend server and the prod-built Angular frontend static files.

project root/
|-- api - Spring Boot, Kotlin-based backend
|-- ui - Angular frontend
\-- docker - Misc. Docker support for development
* `mvn package` may work file, but the `api` module depends on artifacts from the `ui` module. `mvn install`. Will place the ui artifacts in your local Maven repo, and will decouple your local builds from the present of the jar file being present in `ui/target`

The [API](./api/README.md) and [UI](./ui/README.md) modules have their own README.md files with more specific information about those layers.

### Configuration
* This project makes use of 2 similar configurations, labelled in this documentation as "Quickstart" and "Development".
* OSMT requires an OAuth2 provider. It is preconfigured for Okta, but you can use any provider.

[comment]: <> (#### Quickstart Configuration)
#### Quickstart Configuration

[comment]: <> (The Quickstart configuration uses the `docker-compose.yml` file in the project root to stand up a non-production OSMT stack. This file builds a Docker image with Java 11 and Maven, builds the UI and API modules as a fat jar, and then stands up an application stack with the back-end dependencies &#40;MySQL, ElasticSearch, and Redis&#41; and a Spring application using the fat jar.)
The Quickstart configuration uses the `docker-compose.yml` file in the project root to stand up a non-production OSMT stack. This file builds a Docker image with Java 11 and Maven, builds the UI and API modules as a fat jar, and then stands up an application stack with the back-end dependencies (MySQL, ElasticSearch, and Redis) and a Spring application using the fat jar.

[comment]: <> (* This configuration could inform how to configure a production OSMT instance, but it is not intended for a production deployment.)
* This configuration could inform how to configure a production OSMT instance, but it is not intended for a production deployment.

[comment]: <> (The Quickstart configuration is deployed with a single docker-compose command. These steps below are the general process. Follow the guidance in [Environment files for Quickstart and Development Stacks]&#40;#environment-files-for-Quickstart-and-development-stacks&#41; for more details.)
The Quickstart configuration is deployed with a single docker-compose command. These steps below are the general process. Follow the guidance in [Environment files for Quickstart and Development Stacks](#environment-files-for-Quickstart-and-development-stacks) for more details.

[comment]: <> (1. Create file named `osmt-quickstart.env` in the project root. This file will be ignored by git.)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this file name 'osmt-quickstart.env' is not consistent with the name provided under Environment files for QuickStart and developmenet Stacks section. File is named as 'osmt.env'.


[comment]: <> (2. From the project root, run this command:)

[comment]: <> ( - `docker-compose --env-file osmt-quickstart.env up --build`)

[comment]: <> (3. Import any skills-related data you plan to use in your Quickstart instance)

[comment]: <> ( - See [Importing Skills, BLS, and O*NET]&#40;./api/README.md#importing-skills-bls-and-onet&#41; for details.)

[comment]: <> (4. Perform an initial index in ElasticSearch. OSMT will return an error if you skip this step.)

[comment]: <> ( - From the `api` directory, run these commands:)

[comment]: <> ( - `mvn clean package`)

[comment]: <> ( - `mvn -Dspring-boot.run.profiles=dev,reindex springboot:run`)

[comment]: <> ( - See [Elasticsearch indexing]&#40;./api/README.md#elasticsearch-indexing&#41; for details.)

[comment]: <> (5. Open `http://localhost:8080` in your browser.)
1. Create file named `osmt-quickstart.env` in the project root. This file will be ignored by git.
2. From the project root, run this command:
- `docker-compose --env-file osmt-quickstart.env up --build`
3. Import any skills-related data you plan to use in your Quickstart instance
- See [Importing Skills, BLS, and O*NET](./api/README.md#importing-skills-bls-and-onet) for details.
4. Open `http://localhost:8080` in your browser.

#### Development Configuration
The Development configuration uses the `dev-stack.yml` docker-compose file in the `docker` directory, for standing up just the back-end dependencies and doing active development in the Spring or Angular layers.
Expand Down Expand Up @@ -115,10 +101,18 @@ You can use files following this pattern to store your OAuth2 secrets locally an
```
ENVIRONMENT=dev,apiserver,oauth2-okta
BASE_DOMAIN=localhost:8080
REDIS_URI=docker_redis_1:6379
DB_URI=osmt_db_user:password@docker_db_1:3306
ELASTICSEARCH_URI=http://docker_elasticsearch_1:9200
FRONTEND_URL=http://localhost:8080

DB_NAME=osmt_db
DB_USER=osmt_db_user
DB_PASSWORD=password
MYSQL_ROOT_PASSWORD=root_password
MIGRATIONS_ENABLED=true
REINDEX_ELASTICSEARCH=true

ELASTICSEARCH_URI=http://docker_elasticsearch_1:9200
REDIS_URI=docker_redis_1:6379

OAUTH_ISSUER=https://abcdefg.okta.com
OAUTH_CLIENTID=123456qwerty
OAUTH_CLIENTSECRET=2354asdf
Expand Down
2 changes: 1 addition & 1 deletion api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ The general import sequence should be:
3. O*NET (```--import-type=onet```)
4. Reindex Elasticsearch

_Please refer import folder under project root to get sample files for testing purpose only.
_Please refer import folder under project root to get sample files for testing purpose only._

### Running batch skill / collection import from the jar:
```
Expand Down
9 changes: 7 additions & 2 deletions api/src/main/resources/config/application.properties
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
#logging.level.org.springframework=DEBUG

# Database settings
db.name=${DB_NAME:osmt_db}
#db.uri <username>:<password>@<host>:<port>
db.uri=${DB_URI:osmt_db_user:password@0.0.0.0:3306}
db.user=${DB_USER:osmt_db_user}
db.password=${DB_PASSWORD:password}
db.uri=${DB_URI:${db.user}:${db.password}@0.0.0.0:3306}
db.composedUrl=jdbc:mysql://${db.uri}/${db.name}
db.driver=com.mysql.cj.jdbc.Driver
db.showMissingCreateTableStatements=false
Expand All @@ -20,6 +23,8 @@ spring.session.redis.namespace=spring:session

# Flywaydb
spring.flyway.enabled=false
spring.flyway.user=${db.user}
spring.flyway.password=${db.password}
spring.flyway.default-schema=${db.name}
spring.flyway.schemas=${db.name}
spring.flyway.locations=classpath:db/migration
Expand Down
11 changes: 8 additions & 3 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,18 @@ services:
build:
context: ./
dockerfile: Dockerfile
volumes:
- ./import:/opt/osmt/import:rw
environment:
- "ENVIRONMENT=${ENVIRONMENT:-dev,apiserver,oauth2-okta}"
- "BASE_DOMAIN=${BASE_DOMAIN}"
- "FRONTEND_URL=${FRONTEND_URL}"
- "DB_NAME=${DB_NAME}"
- "DB_USER=${DB_USER}"
- "DB_PASSWORD=${DB_PASSWORD}"
- "DB_URI=${DB_USER}:${DB_PASSWORD}@db:3306"
- "MIGRATIONS_ENABLED=${MIGRATIONS_ENABLED}"
- "REINDEX_ELASTICSEARCH=${REINDEX_ELASTICSEARCH}"
- "ELASTICSEARCH_URI=elasticsearch:9200"
- "REDIS_URI=redis:6379"
- "OAUTH_ISSUER=${OAUTH_ISSUER}"
Expand Down Expand Up @@ -59,15 +64,15 @@ services:

redis:
image: library/redis:6.0.6
networks:
- osmt
ports:
- "6379:6379"
networks:
- osmt

networks:
osmt:
driver: bridge

volumes:
osmt_sql_db:
elastic_data:
elastic_data:
98 changes: 83 additions & 15 deletions docker/bin/docker_entrypoint.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,24 @@
#!/bin/bash

function build_reindex_profile_string() {
# accept the $ENVIRONMENT env var, i.e. "test,apiserver,oauth2-okta"
declare env_arg=${1}

declare reindex_profile="reindex"

# If $ENVIRONMENT contains the SDLC env from one of these Spring application profiles,
# then append it to the reindex profile string
declare -ar sdlc_env_list=("dev" "test" "review" "stage")

for sdlc_env in "${sdlc_env_list[@]}"; do
if grep -q "${sdlc_env}" <<<"${env_arg}"; then
reindex_profile="${reindex_profile},${sdlc_env}"
fi
done

echo "${reindex_profile}"
}

BASE_DIR=/opt/osmt

cd ${BASE_DIR} || exit
Expand Down Expand Up @@ -57,24 +76,73 @@ if [[ -z "${MIGRATIONS_ENABLED}" ]]; then
echo " Defaulting to MIGRATIONS_ENABLED=${MIGRATIONS_ENABLED}"
fi

if [[ -z "${REINDEX_ELASTICSEARCH}" ]]; then
REINDEX_ELASTICSEARCH=false
echo "Missing environment 'REINDEX_ELASTICSEARCH'"
echo " Defaulting to REINDEX_ELASTICSEARCH=${REINDEX_ELASTICSEARCH}"
fi

if [[ -z "${FRONTEND_URL}" ]]; then
FRONTEND_URL="http://${BASE_DOMAIN}"
echo "Missing environment 'FRONTEND_URL'"
echo " Defaulting to FRONTEND_URL=${FRONTEND_URL}"
fi

if [[ ${MISSING_ARGS} != 0 ]]; then
echo "Missing ${MISSING_ARGS} shell variable(s), exiting.."
exit 128
else
fi

# The containerized Spring app needs an initial ElasticSearch index, or it returns 500s.

# convert REINDEX_ELASTICSEARCH to lowercase and compare to "true"
if [[ $(echo "$REINDEX_ELASTICSEARCH" | awk '{print tolower($0)}') == "true" ]]; then
declare REINDEX_SPRING_PROFILE="$(build_reindex_profile_string "${ENVIRONMENT}")"

JAVA_CMD="/bin/java
-Dspring.profiles.active=${ENVIRONMENT}
-Dapp.baseDomain=${BASE_DOMAIN}
-Dredis.uri=${REDIS_URI}
-Ddb.uri=${DB_URI}
-Des.uri=${ELASTICSEARCH_URI}
-Dokta.oauth2.issuer=${OAUTH_ISSUER}
-Dokta.oauth2.clientId=${OAUTH_CLIENTID}
-Dokta.oauth2.clientSecret=${OAUTH_CLIENTSECRET}
-Dokta.oauth2.audience=${OAUTH_AUDIENCE}
-Dspring.flyway.enabled=${MIGRATIONS_ENABLED}
-jar ${BASE_DIR}/bin/osmt.jar"

echo "Starting OSMT..."
${JAVA_CMD}
-Dspring.profiles.active=${REINDEX_SPRING_PROFILE}
-Dredis.uri=${REDIS_URI}
-Ddb.uri=${DB_URI}
-Des.uri=${ELASTICSEARCH_URI}
-Dspring.flyway.enabled=${MIGRATIONS_ENABLED}
-jar ${BASE_DIR}/bin/osmt.jar"

echo "---------------------------------------------------------------------------------------------------------------------------------------"
echo "Building initial index in OSMT ElasticSearch using ${REINDEX_SPRING_PROFILE} Spring profiles..."
declare return_code=1
until [ ${return_code} -eq 0 ]; do
${JAVA_CMD}
return_code=$?
if [[ ${return_code} -ne 0 ]]; then
echo "Retrying in 10 seconds..."
fi
sleep 10
done
fi


JAVA_CMD="/bin/java
-Dspring.profiles.active=${ENVIRONMENT}
-Dapp.baseDomain=${BASE_DOMAIN}
-Dapp.frontendUrl=${FRONTEND_URL}
-Dredis.uri=${REDIS_URI}
-Ddb.uri=${DB_URI}
-Des.uri=${ELASTICSEARCH_URI}
-Dokta.oauth2.issuer=${OAUTH_ISSUER}
-Dokta.oauth2.clientId=${OAUTH_CLIENTID}
-Dokta.oauth2.clientSecret=${OAUTH_CLIENTSECRET}
-Dokta.oauth2.audience=${OAUTH_AUDIENCE}
-Dspring.flyway.enabled=${MIGRATIONS_ENABLED}
-jar ${BASE_DIR}/bin/osmt.jar"

echo "---------------------------------------------------------------------------------------------------------------------------------------"
echo "Starting OSMT Spring Boot application using ${ENVIRONMENT} Spring profiles..."
return_code=1
until [ ${return_code} -eq 0 ]; do
${JAVA_CMD}
return_code=$?
if [[ ${return_code} -ne 0 ]]; then
echo "Retrying in 10 seconds..."
fi
sleep 10
done
4 changes: 2 additions & 2 deletions docker/dev-stack.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
version: '3.3'
services:
db:
image: library/mysql:8
image: library/mysql:8.0
command: --default-authentication-plugin=mysql_native_password --character-set-server=utf8mb3 --collation-server=utf8mb3_unicode_ci
volumes:
- osmt_sql_db:/var/lib/mysql:rw
Expand All @@ -14,7 +14,7 @@ services:
- "MYSQL_ROOT_PASSWORD=password"
- "MYSQL_USER=user"
ports:
- 3306:3306
- "3306:3306"
networks:
- osmt
elasticsearch:
Expand Down
2 changes: 1 addition & 1 deletion docker/mysql-init/1init.sql
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
CREATE DATABASE IF NOT EXISTS osmt_db character set UTF8mb3 collate utf8mb3_unicode_ci;

/* CHANGE TO SECURE VALUES! */
CREATE USER 'osmt_db_user'@'%' IDENTIFIED BY 'password';
CREATE USER IF NOT EXISTS 'osmt_db_user'@'%' IDENTIFIED BY 'password';
GRANT ALL ON osmt_db.* TO 'osmt_db_user'@'%';
Loading