Source code for idmtools_platform_local.infrastructure.postgres
"""idmtools postgres service. Used for experiment data.
Copyright 2021, Bill & Melinda Gates Foundation. All rights reserved.
"""
import time
from dataclasses import dataclass
from logging import getLogger, DEBUG
from typing import Dict, NoReturn
from docker.models.containers import Container
from idmtools.core.system_information import get_system_information
from idmtools_platform_local.infrastructure.base_service_container import BaseServiceContainer
logger = getLogger(__name__)
[docs]@dataclass
class PostgresContainer(BaseServiceContainer):
    """Defines the postgres container for the local platform."""
    host_data_directory: str = None
    port: int = 5432
    mem_limit: str = '128m'
    mem_reservation: str = '32m'
    run_as: str = None
    image: str = 'postgres:11.4'
    container_name: str = 'idmtools_postgres'
    # TODO Make this secure by loading from keyring or encrypted file and then pass through docker screts
    password: str = 'idmtools'
    data_volume_name: str = 'idmtools_local_postgres'
    config_prefix: str = 'postgres_'
    def __post_init__(self):
        """Constructor."""
        system_info = get_system_information()
        if self.run_as is None:
            self.run_as = system_info.user_group_str
[docs]    def get_configuration(self) -> Dict:
        """
        Returns the docker config for the postgres container.
        Returns:
            (dict) Dictionary representing the docker config for the postgres container
        """
        postgres_volumes = {
            self.data_volume_name: dict(bind='/var/lib/postgresql/data', mode='rw')
        }
        port_bindings = self._get_optional_port_bindings(self.port, 5432)
        container_config = self.get_common_config(container_name=self.container_name, image=self.image,
                                                  port_bindings=port_bindings,
                                                  volumes=postgres_volumes, mem_limit=self.mem_limit,
                                                  network=self.network,
                                                  mem_reservation=self.mem_reservation,
                                                  environment=['POSTGRES_USER=idmtools',
                                                               f'POSTGRES_PASSWORD={self.password}'])
        if logger.isEnabledFor(DEBUG):
            logger.debug(f"Postgres Config: {container_config}")
        return container_config 
[docs]    def create(self, spinner=None) -> Container:
        """Create our postgres container.
        Here we create the postgres data volume before creating the container.
        """
        self.create_postgres_volume()
        result = super().create(spinner)
        # postgres will restart once so we should watch it again
        time.sleep(0.5)
        self.wait_on_status(result)
        return result 
[docs]    def create_postgres_volume(self) -> NoReturn:
        """
        Creates our postgres volume.
        Returns:
            None
        """
        postgres_volume = self.client.volumes.list(filters=dict(name=self.data_volume_name))
        if not postgres_volume:
            self.client.volumes.create(name=self.data_volume_name)