0

After searching stackoverflow for a while, I found plenty of ways to check if dockerized database service is ready before connection. So I include both of them here.

first one is written in bash script and I found it in here

if [ "$DATABASE" = "postgres" ]
then
    echo "Waiting for postgres..."

    while ! nc -z $SQL_HOST $SQL_PORT; do
      sleep 0.1
    done

    echo "PostgreSQL started"
fi

python manage.py flush --no-input
python manage.py migrate

exec "$@"

The second one is written in python and I found it in here:

class Command(BaseCommand):
"""Django command that waits for database to be available"""

    def handle(self, *args, **options):
        """Handle the command"""
        self.stdout.write('Waiting for database...')
        db_conn = None
        while not db_conn:
            try:
                connection.ensure_connection()
                db_conn = True
            except OperationalError:
                self.stdout.write('Database unavailable, waiting 1 second...')
                time.sleep(1)

        self.stdout.write(self.style.SUCCESS('Database available!'))

I use this docker command ENTRYPOINT ["/usr/src/app/entrypoint.sh"] to run the first one.

I know how to write unit tests for the second one, because it's in python. it could be something like this for example:

from unittest.mock import patch
# Use patch to to simulate db for being available or not
from django.core.management import call_command
from django.test import TestCase


class CommandTests(TestCase):
    def test_wait_for_db_ready(self):
        """Test waiting for db when db is available"""
        with patch('django.db.utils.ConnectionHandler.__getitem__') as gi:
            gi.return_value = True
            call_command('wait_for_db')
            self.assertEqual(gi.call_count, 1)

But can anyone help me find a way to write tests for the first one (the bash script)?

In addition, Can anybody name what are the drawbacks and advantages of each method and also if there exists some other important considerations for writing such function? Thanks

Masoud Masoumi Moghadam
  • 1,094
  • 3
  • 23
  • 45
  • Please read [Why is "Can someone help me?" not an actual question?](https://meta.stackoverflow.com/q/284236/354577) Also, questions that are primarily opinion-based are off-topic. – ChrisGPT was on strike Nov 02 '19 at 16:39
  • @Chris Changed the topic! – Masoud Masoumi Moghadam Nov 02 '19 at 16:48
  • There are unit-test frameworks for shell scripts too. Most Docker images have a POSIX-compatible Bourne shell, but if you have Python available, you might find it easier to test and to use higher-level abstractions. I'm not totally sure what sort of answer you're hoping for here. – David Maze Nov 02 '19 at 17:20

1 Answers1

1

The reason that you might not want a management command to check the status of the database is that django may try to connect to the database before running your management command which kind of makes it impossible for your script to detect whether the database is down. Because if the database is down, django will fail to connect to it and throw an exception before running the management command.

The drawbacks of the bash script are that it requires you to install additional os-level dependencies (in this case, netcat). It's not that big of a deal, but it does make your docker image larger.

2ps
  • 15,099
  • 2
  • 27
  • 47