コード例 #1
0
class PostgresTest(unittest.TestCase):
    """Test the public API provided by the `Postgres` class"""
    def setUp(self):
        """Set up a temporary database cluster for testing potentially destructive operations"""
        self.pg_test = PGTest()
        self.postgres = Postgres(port=self.pg_test.port,
                                 interactive=False,
                                 quiet=True)
        self.dbuser = '******'
        self.dbpass = '******'
        self.dbname = 'aiida_db'

    def _setup_postgres(self):
        self.postgres.dbinfo = self.pg_test.dsn
        self.postgres.determine_setup()

    def test_determine_setup_fail(self):
        self.postgres.set_port('11111')
        setup_success = self.postgres.determine_setup()
        self.assertFalse(setup_success)

    def test_determine_setup_success(self):
        self._setup_postgres()
        self.assertTrue(self.postgres.pg_execute)

    def test_setup_fail_callback(self):
        """Make sure `determine_setup` works despite wrong initial values in case of correct callback"""
        def correct_setup(interactive, dbinfo):  # pylint: disable=unused-argument
            return self.pg_test.dsn

        self.postgres.set_port(11111)
        self.postgres.set_setup_fail_callback(correct_setup)
        self.postgres.determine_setup()
        self.assertTrue(self.postgres.pg_execute)

    @mock.patch('aiida.control.postgres._try_connect',
                new=_try_connect_always_fail)
    @mock.patch('aiida.control.postgres._try_subcmd')
    def test_fallback_on_subcmd(self, try_subcmd):
        """Ensure that accessing postgres via subcommand is tried if psychopg does not work."""
        self._setup_postgres()
        self.assertTrue(try_subcmd.call_count >= 1)

    def test_create_drop_db_user(self):
        """Check creating and dropping a user works"""
        self._setup_postgres()
        self.postgres.create_dbuser(self.dbuser, self.dbpass)
        self.assertTrue(self.postgres.dbuser_exists(self.dbuser))
        self.postgres.drop_dbuser(self.dbuser)
        self.assertFalse(self.postgres.dbuser_exists(self.dbuser))

    def test_create_drop_db(self):
        """Check creating & destroying a database"""
        self._setup_postgres()
        self.postgres.create_dbuser(self.dbuser, self.dbpass)
        self.postgres.create_db(self.dbuser, self.dbname)
        self.assertTrue(self.postgres.db_exists(self.dbname))
        self.postgres.drop_db(self.dbname)
        self.assertFalse(self.postgres.db_exists(self.dbname))
コード例 #2
0
    def profile_delete(self, *args):
        """ Deletes profile

        Asks whether to delete associated database and associated database
        user.

        Specify argument '--force' to skip any questions warning about loss of
        data.
        """
        from aiida.common.setup import get_or_create_config, update_config
        import os.path
        from urlparse import urlparse

        args = list(args)
        if '--force' in args:
            force = True
            args.remove('--force')
        else:
            force = False

        confs = get_or_create_config()
        profiles = confs.get('profiles', {})
        users = [
            profiles[name].get('AIIDADB_USER', '') for name in profiles.keys()
        ]

        profiles_to_delete = args
        for profile_to_delete in profiles_to_delete:
            try:
                profile = profiles[profile_to_delete]
            except KeyError:
                print("Profile '{}' does not exist".format(profile_to_delete))
                continue

            postgres = Postgres(port=profile.get('AIIDADB_PORT'),
                                interactive=True,
                                quiet=False)
            postgres.determine_setup()
            print postgres.dbinfo

            db_name = profile.get('AIIDADB_NAME', '')
            if not postgres.db_exists(db_name):
                print(
                    "Associated database '{}' does not exist.".format(db_name))
            elif force or click.confirm("Delete associated database '{}'?\n" \
                             "WARNING: All data will be lost.".format(db_name)):
                print("Deleting database '{}'.".format(db_name))
                postgres.drop_db(db_name)

            user = profile.get('AIIDADB_USER', '')
            if not postgres.dbuser_exists(user):
                print("Associated database user '{}' does not exist.".format(
                    user))
            elif users.count(user) > 1:
                print("Associated database user '{}' is used by other profiles "\
                      "and will not be deleted.".format(user))
            elif force or click.confirm(
                    "Delete database user '{}'?".format(user)):
                print("Deleting user '{}'.".format(user))
                postgres.drop_dbuser(user)

            repo_uri = profile.get('AIIDADB_REPOSITORY_URI', '')
            repo_path = urlparse(repo_uri).path
            repo_path = os.path.expanduser(repo_path)
            if not os.path.isabs(repo_path):
                print("Associated file repository '{}' does not exist."\
                      .format(repo_path))
            elif not os.path.isdir(repo_path):
                print("Associated file repository '{}' is not a directory."\
                       .format(repo_path))
            elif force or click.confirm("Delete associated file repository '{}'?\n" \
                               "WARNING: All data will be lost.".format(repo_path)):
                print("Deleting directory '{}'.".format(repo_path))
                import shutil
                shutil.rmtree(repo_path)

            if force or click.confirm("Delete configuration for profile '{}'?\n" \
                             "WARNING: Permanently removes profile from the list of AiiDA profiles."\
                             .format(profile_to_delete)):
                print("Deleting configuration for profile '{}'.".format(
                    profile_to_delete))
                del profiles[profile_to_delete]
                update_config(confs)
コード例 #3
0
def profile_delete(force, profiles):
    """
    Delete PROFILES separated by space from aiida config file
    along with its associated database and repository.
    """
    from aiida.common.setup import get_or_create_config, update_config
    import os.path
    from urlparse import urlparse

    echo.echo('profiles: {}'.format(', '.join(profiles)))

    confs = get_or_create_config()
    available_profiles = confs.get('profiles', {})
    users = [
        available_profiles[name].get('AIIDADB_USER', '')
        for name in available_profiles.keys()
    ]

    for profile_name in profiles:
        try:
            profile = available_profiles[profile_name]
        except KeyError:
            echo.echo_info("Profile '{}' does not exist".format(profile_name))
            continue

        postgres = Postgres(port=profile.get('AIIDADB_PORT'),
                            interactive=True,
                            quiet=False)
        postgres.dbinfo["user"] = profile.get('AIIDADB_USER')
        postgres.dbinfo["host"] = profile.get('AIIDADB_HOST')
        postgres.determine_setup()

        import json
        echo.echo(json.dumps(postgres.dbinfo, indent=4))

        db_name = profile.get('AIIDADB_NAME', '')
        if not postgres.db_exists(db_name):
            echo.echo_info(
                "Associated database '{}' does not exist.".format(db_name))
        elif force or click.confirm("Delete associated database '{}'?\n" \
                                    "WARNING: All data will be lost.".format(db_name)):
            echo.echo_info("Deleting database '{}'.".format(db_name))
            postgres.drop_db(db_name)

        user = profile.get('AIIDADB_USER', '')
        if not postgres.dbuser_exists(user):
            echo.echo_info(
                "Associated database user '{}' does not exist.".format(user))
        elif users.count(user) > 1:
            echo.echo_info("Associated database user '{}' is used by other profiles " \
                  "and will not be deleted.".format(user))
        elif force or click.confirm("Delete database user '{}'?".format(user)):
            echo.echo_info("Deleting user '{}'.".format(user))
            postgres.drop_dbuser(user)

        repo_uri = profile.get('AIIDADB_REPOSITORY_URI', '')
        repo_path = urlparse(repo_uri).path
        repo_path = os.path.expanduser(repo_path)
        if not os.path.isabs(repo_path):
            echo.echo_info("Associated file repository '{}' does not exist." \
                  .format(repo_path))
        elif not os.path.isdir(repo_path):
            echo.echo_info("Associated file repository '{}' is not a directory." \
                  .format(repo_path))
        elif force or click.confirm("Delete associated file repository '{}'?\n" \
                                    "WARNING: All data will be lost.".format(repo_path)):
            echo.echo_info("Deleting directory '{}'.".format(repo_path))
            import shutil
            shutil.rmtree(repo_path)

        if force or click.confirm("Delete configuration for profile '{}'?\n" \
                                  "WARNING: Permanently removes profile from the list of AiiDA profiles." \
                                          .format(profile_name)):
            echo.echo_info("Deleting configuration for profile '{}'.".format(
                profile_name))
            del available_profiles[profile_name]
            update_config(confs)