-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
chore: add script to start docker dependencies #233
Changes from 4 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -9,6 +9,15 @@ | |||||||||||||||||||
[Cheese Backend](https://github.com/SageSeekerSociety/cheese-backend) | ||||||||||||||||||||
The backend of the cheese Q&A system. | ||||||||||||||||||||
|
||||||||||||||||||||
## Run without installation | ||||||||||||||||||||
|
||||||||||||||||||||
If you only want to start the application, you can use `docs/scripts/cheese-start.sh` and `docs/scripts/cheese-restart.sh` | ||||||||||||||||||||
to start and restart the application. You do not need to do anything else if you use these scripts. By default, after application | ||||||||||||||||||||
is started in this way, it will be available at `http://localhost:3000`. | ||||||||||||||||||||
|
||||||||||||||||||||
Notice that these scripts use the latest docker image on GitHub built from the `dev` branch, so it has nothing to do with your local code. | ||||||||||||||||||||
If you want to use your local code, you need to install the dependencies and run the app manually, as described below. | ||||||||||||||||||||
|
||||||||||||||||||||
## Installation | ||||||||||||||||||||
|
||||||||||||||||||||
Before installing this backend, ensure that you have installed the pnpm package manager. If you have not yet installed it, you can install it with the following command: | ||||||||||||||||||||
|
@@ -23,32 +32,39 @@ After this repo is cloned, you should install the dependencies with the followin | |||||||||||||||||||
pnpm install | ||||||||||||||||||||
``` | ||||||||||||||||||||
|
||||||||||||||||||||
You need to create a database for this backend. We recommend you to use PostgreSQL because we have tested the app with PostgreSQL, and it works very well. | ||||||||||||||||||||
You need to create a database for this backend. Currently, we only support PostgreSQL. | ||||||||||||||||||||
Also, you need to set up an Elasticsearch instance. It is used to provide full-text search feature. | ||||||||||||||||||||
|
||||||||||||||||||||
If you want to use other databases, you need to modify src/app.prisma. Replace | ||||||||||||||||||||
Setting up PostgreSQL and Elasticsearch can be complicated, so we recommend you to use Docker to set up the environment. | ||||||||||||||||||||
You can use `docs/scripts/dependency-start.sh` and `docs/scripts/dependency-restart.sh` to start and restart the dependencies. | ||||||||||||||||||||
If you setup dependencies in this way, then simply use `docs/scripts/dependency.env` as your `.env` file. | ||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Correct the verb form for setting up dependencies. The instructions on lines 38-40 use "setup" as a verb, which is incorrect. The correct verb form is "set up". This issue was flagged by static analysis and needs correction to maintain professionalism in the documentation. Apply this correction to use the correct verb form: - If you setup dependencies in this way, then simply use `docs/scripts/dependency.env` as your `.env` file.
+ If you set up dependencies in this way, then simply use `docs/scripts/dependency.env` as your `.env` file. Committable suggestion
Suggested change
ToolsLanguageTool
|
||||||||||||||||||||
|
||||||||||||||||||||
```prisma | ||||||||||||||||||||
provider = "postgresql" | ||||||||||||||||||||
```bash | ||||||||||||||||||||
docs/scripts/dependency-start.sh | ||||||||||||||||||||
cp docs/scripts/dependency.env .env | ||||||||||||||||||||
``` | ||||||||||||||||||||
|
||||||||||||||||||||
with what you want to use, such as | ||||||||||||||||||||
If you setup dependencies manually, you need to modify the `.env` file according to your condition. | ||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Correct the verb form for manual dependency setup. Similar to the previous comment, the phrase "If you setup dependencies manually" on line 47 also incorrectly uses "setup" as a verb. Correcting this to "set up" will improve the grammatical accuracy of the document. Here is the suggested correction: - If you setup dependencies manually, you need to modify the `.env` file according to your condition.
+ If you set up dependencies manually, you need to modify the `.env` file according to your condition. Committable suggestion
Suggested change
ToolsLanguageTool
|
||||||||||||||||||||
Copy `sample.env` to `.env` and modify according to your condition. | ||||||||||||||||||||
|
||||||||||||||||||||
```prisma | ||||||||||||||||||||
provider = "mysql" | ||||||||||||||||||||
```bash | ||||||||||||||||||||
cp sample.env .env | ||||||||||||||||||||
``` | ||||||||||||||||||||
|
||||||||||||||||||||
and recompile the prisma client with the following command: | ||||||||||||||||||||
|
||||||||||||||||||||
Once you believe you have set up the environment correctly, you can run the following command to initialize database schema: | ||||||||||||||||||||
```bash | ||||||||||||||||||||
pnpm build-prisma | ||||||||||||||||||||
pnpm prisma db push | ||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add missing article before 'database schema'. The command instructions on lines 54-57 are missing an article before "database schema". Adding "the" before "database schema" will improve the readability of the instructions. Propose adding the missing article for grammatical correctness: - Once you believe you have set up the environment correctly, you can run the following command to initialize database schema:
+ Once you believe you have set up the environment correctly, you can run the following command to initialize the database schema: Committable suggestion
Suggested change
ToolsLanguageTool
|
||||||||||||||||||||
``` | ||||||||||||||||||||
|
||||||||||||||||||||
Also, you need to set up an Elasticsearch instance. It is used to provide full-text search feature. | ||||||||||||||||||||
|
||||||||||||||||||||
Copy `sample.env` to `.env` and modify according to your condition. | ||||||||||||||||||||
You need to start the app once before running tests. | ||||||||||||||||||||
```bash | ||||||||||||||||||||
pnpm start | ||||||||||||||||||||
``` | ||||||||||||||||||||
|
||||||||||||||||||||
Now, you can run tests with the following command to ensure that the app is working correctly: | ||||||||||||||||||||
```bash | ||||||||||||||||||||
cp sample.env .env | ||||||||||||||||||||
pnpm test | ||||||||||||||||||||
``` | ||||||||||||||||||||
|
||||||||||||||||||||
## Running the app | ||||||||||||||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
#!/bin/sh | ||
sudo systemctl start docker | ||
sudo docker restart elasticsearch postgres cheese_legacy |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,63 @@ | ||||||||||||||||||||||||||||||
#!/bin/sh | ||||||||||||||||||||||||||||||
sudo systemctl start docker.service | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
sudo docker network create cheese_network | ||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Check if the Docker network already exists. The command to create the Docker network is correct, but it assumes the network does not already exist. Consider adding a check to avoid errors. +if ! sudo docker network ls | grep -q cheese_network; then
+ sudo docker network create cheese_network
+fi Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
sudo docker run -d \ | ||||||||||||||||||||||||||||||
--name elasticsearch \ | ||||||||||||||||||||||||||||||
--network cheese_network \ | ||||||||||||||||||||||||||||||
-e discovery.type=single-node \ | ||||||||||||||||||||||||||||||
-e xpack.security.enabled=true \ | ||||||||||||||||||||||||||||||
-e ELASTIC_USERNAME=elastic \ | ||||||||||||||||||||||||||||||
-e ELASTIC_PASSWORD=elastic \ | ||||||||||||||||||||||||||||||
--health-cmd="curl http://localhost:9200/_cluster/health" \ | ||||||||||||||||||||||||||||||
--health-interval=10s \ | ||||||||||||||||||||||||||||||
--health-timeout=5s \ | ||||||||||||||||||||||||||||||
--health-retries=10 \ | ||||||||||||||||||||||||||||||
-p 9200:9200 \ | ||||||||||||||||||||||||||||||
docker.elastic.co/elasticsearch/elasticsearch:8.12.1 | ||||||||||||||||||||||||||||||
Comment on lines
+6
to
+18
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Avoid using
-sudo docker run -d \
+docker run -d \
--name elasticsearch \
--network cheese_network \
-e discovery.type=single-node \
-e xpack.security.enabled=true \
-e ELASTIC_USERNAME=elastic \
-e ELASTIC_PASSWORD=elastic \
--health-cmd="curl http://localhost:9200/_cluster/health" \
--health-interval=10s \
--health-timeout=5s \
--health-retries=10 \
-p 9200:9200 \
docker.elastic.co/elasticsearch/elasticsearch:8.12.1
|
||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
sudo docker run -d \ | ||||||||||||||||||||||||||||||
--name postgres \ | ||||||||||||||||||||||||||||||
--network cheese_network \ | ||||||||||||||||||||||||||||||
-e POSTGRES_PASSWORD=postgres \ | ||||||||||||||||||||||||||||||
--health-cmd="pg_isready" \ | ||||||||||||||||||||||||||||||
--health-interval=10s \ | ||||||||||||||||||||||||||||||
--health-timeout=5s \ | ||||||||||||||||||||||||||||||
--health-retries=5 \ | ||||||||||||||||||||||||||||||
-p 5432:5432 \ | ||||||||||||||||||||||||||||||
postgres | ||||||||||||||||||||||||||||||
Comment on lines
+20
to
+29
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Avoid using
-sudo docker run -d \
+docker run -d \
--name postgres \
--network cheese_network \
-e POSTGRES_PASSWORD=postgres \
--health-cmd="pg_isready" \
--health-interval=10s \
--health-timeout=5s \
--health-retries=5 \
-p 5432:5432 \
postgres
|
||||||||||||||||||||||||||||||
echo "Wait for 5 seconds please..." | ||||||||||||||||||||||||||||||
sleep 5 | ||||||||||||||||||||||||||||||
sudo docker exec -i postgres bash << EOF | ||||||||||||||||||||||||||||||
sed -i -e 's/max_connections = 100/max_connections = 1000/' /var/lib/postgresql/data/postgresql.conf | ||||||||||||||||||||||||||||||
sed -i -e 's/shared_buffers = 128MB/shared_buffers = 2GB/' /var/lib/postgresql/data/postgresql.conf | ||||||||||||||||||||||||||||||
EOF | ||||||||||||||||||||||||||||||
sudo docker restart --time 0 postgres | ||||||||||||||||||||||||||||||
Comment on lines
+30
to
+36
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Avoid using If the user is part of the Docker group, -sudo docker exec -i postgres bash << EOF
+docker exec -i postgres bash << EOF
sed -i -e 's/max_connections = 100/max_connections = 1000/' /var/lib/postgresql/data/postgresql.conf
sed -i -e 's/shared_buffers = 128MB/shared_buffers = 2GB/' /var/lib/postgresql/data/postgresql.conf
EOF
-sudo docker restart --time 0 postgres
+docker restart --time 0 postgres Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
sudo docker run -d \ | ||||||||||||||||||||||||||||||
--name cheese_legacy \ | ||||||||||||||||||||||||||||||
--network cheese_network \ | ||||||||||||||||||||||||||||||
-p 3000:3000 \ | ||||||||||||||||||||||||||||||
-e PORT=3000 \ | ||||||||||||||||||||||||||||||
-e JWT_SECRET="test-secret" \ | ||||||||||||||||||||||||||||||
-e PRISMA_DATABASE_URL="postgresql://postgres:postgres@postgres:5432/postgres?schema=public&connection_limit=16" \ | ||||||||||||||||||||||||||||||
-e ELASTICSEARCH_NODE=http://elasticsearch:9200/ \ | ||||||||||||||||||||||||||||||
-e ELASTICSEARCH_AUTH_USERNAME=elastic \ | ||||||||||||||||||||||||||||||
-e ELASTICSEARCH_AUTH_PASSWORD=elastic \ | ||||||||||||||||||||||||||||||
-e FILE_UPLOAD_PATH=/app/uploads \ | ||||||||||||||||||||||||||||||
-e DEFAULT_AVATAR_NAME=default.jpg \ | ||||||||||||||||||||||||||||||
-e EMAIL_SMTP_HOST=smtp.example.com \ | ||||||||||||||||||||||||||||||
-e EMAIL_SMTP_PORT=587 \ | ||||||||||||||||||||||||||||||
-e EMAIL_SMTP_SSL_ENABLE=true \ | ||||||||||||||||||||||||||||||
-e EMAIL_SMTP_USERNAME=user@example.com \ | ||||||||||||||||||||||||||||||
-e EMAIL_SMTP_PASSWORD=a_super_strong_password \ | ||||||||||||||||||||||||||||||
-e EMAIL_DEFAULT_FROM="No Reply <noreply@example.com>" \ | ||||||||||||||||||||||||||||||
ghcr.io/sageseekersociety/cheese-backend-dev:dev \ | ||||||||||||||||||||||||||||||
bash -c ' | ||||||||||||||||||||||||||||||
if [ ! -f "FLAG_INIT" ]; then | ||||||||||||||||||||||||||||||
touch FLAG_INIT | ||||||||||||||||||||||||||||||
pnpm prisma db push | ||||||||||||||||||||||||||||||
fi | ||||||||||||||||||||||||||||||
pnpm start | ||||||||||||||||||||||||||||||
' | ||||||||||||||||||||||||||||||
Comment on lines
+38
to
+63
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Avoid using
-sudo docker run -d \
+docker run -d \
--name cheese_legacy \
--network cheese_network \
-p 3000:3000 \
-e PORT=3000 \
-e JWT_SECRET="test-secret" \
-e PRISMA_DATABASE_URL="postgresql://postgres:postgres@postgres:5432/postgres?schema=public&connection_limit=16" \
-e ELASTICSEARCH_NODE=http://elasticsearch:9200/ \
-e ELASTICSEARCH_AUTH_USERNAME=elastic \
-e ELASTICSEARCH_AUTH_PASSWORD=elastic \
-e FILE_UPLOAD_PATH=/app/uploads \
-e DEFAULT_AVATAR_NAME=default.jpg \
-e EMAIL_SMTP_HOST=smtp.example.com \
-e EMAIL_SMTP_PORT=587 \
-e EMAIL_SMTP_SSL_ENABLE=true \
-e EMAIL_SMTP_USERNAME=user@example.com \
-e EMAIL_SMTP_PASSWORD=a_super_strong_password \
-e EMAIL_DEFAULT_FROM="No Reply <noreply@example.com>" \
ghcr.io/sageseekersociety/cheese-backend-dev:dev \
bash -c '
if [ ! -f "FLAG_INIT" ]; then
touch FLAG_INIT
pnpm prisma db push
fi
pnpm start
'
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
#!/bin/sh | ||
sudo systemctl start docker | ||
sudo docker restart elasticsearch postgres |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
#!/bin/sh | ||
sudo systemctl start docker.service | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider removing Using # Add the user to the docker group to avoid using sudo
sudo usermod -aG docker $USER |
||
|
||
sudo docker run -d \ | ||
--name elasticsearch \ | ||
-e discovery.type=single-node \ | ||
-e xpack.security.enabled=true \ | ||
-e ELASTIC_USERNAME=elastic \ | ||
-e ELASTIC_PASSWORD=elastic \ | ||
--health-cmd="curl http://localhost:9200/_cluster/health" \ | ||
--health-interval=10s \ | ||
--health-timeout=5s \ | ||
--health-retries=10 \ | ||
-p 9200:9200 \ | ||
docker.elastic.co/elasticsearch/elasticsearch:8.12.1 | ||
Comment on lines
+4
to
+15
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ensure Elasticsearch credentials are secure. The Elasticsearch credentials ( # Example of using environment variables
-e ELASTIC_USERNAME=$ELASTIC_USERNAME \
-e ELASTIC_PASSWORD=$ELASTIC_PASSWORD \ |
||
|
||
sudo docker run -d \ | ||
--name postgres \ | ||
-e POSTGRES_PASSWORD=postgres \ | ||
--health-cmd="pg_isready" \ | ||
--health-interval=10s \ | ||
--health-timeout=5s \ | ||
--health-retries=5 \ | ||
-p 5432:5432 \ | ||
postgres | ||
Comment on lines
+17
to
+25
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ensure PostgreSQL credentials are secure. The PostgreSQL password is hardcoded. Consider using environment variables or a secure vault to manage sensitive information. # Example of using environment variables
-e POSTGRES_PASSWORD=$POSTGRES_PASSWORD \ |
||
echo "Wait for 5 seconds please..." | ||
sleep 5 | ||
sudo docker exec -i postgres bash << EOF | ||
sed -i -e 's/max_connections = 100/max_connections = 1000/' /var/lib/postgresql/data/postgresql.conf | ||
sed -i -e 's/shared_buffers = 128MB/shared_buffers = 2GB/' /var/lib/postgresql/data/postgresql.conf | ||
EOF | ||
Comment on lines
+28
to
+31
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Avoid inline configuration changes for PostgreSQL. Modifying PostgreSQL configuration files directly within the container can lead to issues with container immutability and reproducibility. Consider using a custom Docker image or a volume to manage configuration changes. # Consider creating a custom Docker image with the necessary configurations
# or mounting a configuration file using a volume. |
||
sudo docker restart --time 0 postgres |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
# The port that the app will listen to | ||
PORT=3000 | ||
|
||
# The secret used to sign the JWT token | ||
# You MUST change this secret to your own secret! | ||
# Otherwise, your app will be as insecure as with an empty admin password! | ||
JWT_SECRET="test-secret" | ||
Comment on lines
+4
to
+7
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ensure a secure, unique JWT_SECRET is used in production. The warning to change the JWT_SECRET to a secure, unique value is crucial for security. Ensure that this is not overlooked during deployment. |
||
|
||
DB_HOST=localhost # set DB_HOST to database to use with docker | ||
DB_USERNAME=postgres | ||
DB_PASSWORD=postgres # your passowrd | ||
DB_PASSWORD_URL_FORMAT=postgres # password in url-format, see https://github.com/prisma/prisma/discussions/15679 | ||
DB_PORT=5432 | ||
DB_NAME=postgres | ||
Comment on lines
+9
to
+14
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use secure methods to handle the database password in production. Ensure that the database password is not hardcoded in production environments. Consider using environment variables or secrets management solutions to handle sensitive information securely. |
||
|
||
# The connection URL of the database for Prisma | ||
# See https://www.prisma.io/docs/orm/reference/connection-urls for more information | ||
# Keep align with the TypeORM configuration | ||
PRISMA_DATABASE_URL="postgresql://${DB_USERNAME}:${DB_PASSWORD_URL_FORMAT}@${DB_HOST}:${DB_PORT}/${DB_NAME}?schema=public&connection_limit=16" | ||
|
||
# The maximum amount of time the interactive transaction can run before being canceled and rolled back. | ||
# See: https://github.com/prisma/prisma/releases/tag/5.10.0 | ||
# See: https://github.com/prisma/prisma/issues/15028 | ||
PRISMA_TRANSACTION_TIMEOUT=60000 # 60s | ||
|
||
# The configuration for Elasticsearch | ||
ELASTICSEARCH_NODE=http://localhost:9200/ | ||
ELASTICSEARCH_MAX_RETRIES=10 | ||
ELASTICSEARCH_REQUEST_TIMEOUT=60000 | ||
ELASTICSEARCH_PING_TIMEOUT=60000 | ||
ELASTICSEARCH_SNIFF_ON_START=true | ||
ELASTICSEARCH_AUTH_USERNAME=elastic | ||
ELASTICSEARCH_AUTH_PASSWORD=elastic | ||
Comment on lines
+26
to
+33
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use secure methods to handle Elasticsearch credentials in production. The Elasticsearch configuration includes sensitive credentials. Ensure these are handled securely, possibly using environment variables or secrets management solutions. |
||
|
||
# The configuration for uploaded files | ||
FILE_UPLOAD_PATH=/tmp/app/uploads | ||
DEFAULT_AVATAR_NAME=default.jpg | ||
|
||
|
||
# The configuration for CORS | ||
CORS_ORIGINS=http://localhost:3000 # use `,` to separate multiple origins | ||
CORS_METHODS=GET,POST,PUT,PATCH,DELETE | ||
CORS_HEADERS=Content-Type,Authorization | ||
CORS_CREDENTIALS=true | ||
|
||
# additionally setup the following if you want to use docker-compose | ||
# to setup environment | ||
POSTGRES_DB=${DB_NAME} | ||
POSTGRES_USER=${DB_USERNAME} | ||
POSTGRES_PASSWORD=${DB_PASSWORD} | ||
|
||
# Email configuration: | ||
EMAIL_SMTP_HOST=smtp.example.com | ||
EMAIL_SMTP_PORT=587 | ||
EMAIL_SMTP_SSL_ENABLE=true | ||
EMAIL_SMTP_USERNAME=user@example.com | ||
EMAIL_SMTP_PASSWORD=a_super_strong_password | ||
EMAIL_DEFAULT_FROM='"No Reply" <noreply@example.com>' | ||
Comment on lines
+52
to
+58
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use secure methods to handle email credentials in production. The email SMTP settings include sensitive credentials. Ensure these are handled securely, possibly using environment variables or secrets management solutions. |
||
|
||
# Email test configuration: | ||
# Enabling email test means when you run test, emails will be sent. | ||
EMAILTEST_ENABLE=false | ||
EMAILTEST_RECEIVER=developer@example.com |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Clarify the instructions for running the application without installation.
The instructions on lines 14-16 introduce the use of Docker scripts for starting and managing the application. However, the phrase "after application is started in this way" is missing an article before "application". This was previously flagged and should be corrected to enhance clarity.
Consider revising the sentence for better clarity and grammatical accuracy:
Committable suggestion
Tools
LanguageTool