def collect_static_content(self):
        """Collect static content of the provided Django project.

        This function should be called only after django.setup() is called.

        Raises:
            StaticContentServeError: If Django environment is not correctly
                setup.
        """

        if not settings.configured:
            raise StaticContentServeError(
                'Django environment is not setup correctly or the settings '
                'module is invalid. We cannot collect static files.')
        cwd = os.getcwd()
        # Change directory to the Django project directory. If we do not do
        # this, static content will be collected in your current directory.
        # This is not expected.
        os.chdir(settings.BASE_DIR)
        try:
            management.call_command(
                'collectstatic', verbosity=0, interactive=False)
        except Exception as e:
            raise crash_handling.UserError(
                'Not able to collect static files.') from e
        finally:
            os.chdir(cwd)
    def setup_django_environment(self,
                                 project_dir: str,
                                 project_name: str,
                                 database_user: str,
                                 database_password: str,
                                 cloud_sql_proxy_port: Optional[int] = None):
        """Setup Django environment.

        This makes Django command calls afterwards affect the newly generated
        project.

        Args:
            project_dir: Absolute directory path to put your Django project.
            project_name: Name of your Django project.
            database_user: The name of the database user. By default it is
                "postgres". This is required for Django app to access database.
            database_password: The database password to set.
            cloud_sql_proxy_port: The port being forwarded by cloud sql proxy.
        """
        os.environ['DATABASE_USER'] = database_user
        os.environ['DATABASE_PASSWORD'] = database_password
        if cloud_sql_proxy_port:
            os.environ['CLOUD_SQL_PROXY_PORT'] = str(cloud_sql_proxy_port)
        sys.path.append(project_dir)
        os.environ['DJANGO_SETTINGS_MODULE'] = '{}.cloud_settings'.format(
            project_name)
        try:
            django.setup()
        except Exception as e:
            raise crash_handling.UserError(
                'Not able to import Django settings file.') from e
 def test_ignore_user_error(self, mock_open_browser, *unused_mocks):
     test_io = io.TestIO()
     test_io.answers.append('Y')  # Agree to open browser to create an issue
     error = KeyError('Test KeyError')
     with self.assertRaises(KeyError):
         try:
             raise crash_handling.UserError() from error
         except Exception as e:
             crash_handling.handle_crash(e, 'command_fake', test_io)
     mock_open_browser.assert_not_called()
Exemplo n.º 4
0
    def migrate_database(self,
                         project_dir: str,
                         project_id: str,
                         instance_name: str,
                         cloud_sql_proxy_path: str = 'cloud_sql_proxy',
                         region: str = 'us-west1',
                         port: Optional[int] = 5432):
        """Migrate to Cloud SQL database.

        This function should be called after we do the following:
            1. Generated the Django project source files.
            2. Setup Django environment so that it is using configuration files
               of the newly generated project.
            3. Created the Cloud SQL instance and database user.

        Args:
            project_dir: Absolute path of the Django project directory.
            project_id: GCP project id.
            instance_name: Name of the Cloud SQL instance where the database you
                want to migrate is in.
            cloud_sql_proxy_path: The command to run your cloud sql proxy.
            region: Where the Cloud SQL instance is in.
            port: The port being forwarded by cloud sql proxy.
        """
        with self.with_cloud_sql_proxy(project_id, instance_name,
                                       cloud_sql_proxy_path, region, port):
            try:
                # The environment variable must exist. This is the prerequisite
                # of calling this function
                settings_module = os.environ['DJANGO_SETTINGS_MODULE']

                # "makemigrations" will generate migration files based on
                # definitions in models.py.
                makemigrations_args = [
                    'django-admin', 'makemigrations',
                    '='.join(['--pythonpath', project_dir]),
                    '='.join(['--settings', settings_module])
                ]
                subprocess.check_call(makemigrations_args,
                                      stdout=subprocess.DEVNULL,
                                      stderr=subprocess.DEVNULL)
                # "migrate" will modify cloud sql database.
                migrate_args = [
                    'django-admin', 'migrate',
                    '='.join(['--pythonpath', project_dir]),
                    '='.join(['--settings', settings_module])
                ]
                subprocess.check_call(migrate_args,
                                      stdout=subprocess.DEVNULL,
                                      stderr=subprocess.DEVNULL)
            except Exception as e:
                raise crash_handling.UserError(
                    'Not able to migrate database.') from e
Exemplo n.º 5
0
    def enable_service_sync(self, project_id: str, service: str):
        """Enable a service for the given project.

        Args:
            project_id: GCP project id.
            service: Name of the service to be enabled. For example,
                "drive.googleapis.com"

        Raises:
            EnableServiceError: When it fails to enable a service.
        """

        service_name = '/'.join(['projects', project_id, 'services', service])
        request = self._service_usage_service.services().enable(
            name=service_name)
        try:
            response = request.execute(num_retries=5)
        except errors.HttpError as e:
            if e.resp.status == 400:
                tos = 'terms of service'
                if tos in str(e):
                    url = 'https://console.developers.google.com/terms/cloud'
                    msg = ('Please accept the terms of service in the Google'
                           'Cloud Console @ {}'.format(url))
                    raise crash_handling.UserError(msg)
            # For all errors that are not related to ToS we want to raise
            raise e

        # When the api call succeed, the response is a Service object.
        # See
        # https://cloud.google.com/service-usage/docs/reference/rest/v1/services/get
        if 'name' not in response:
            raise EnableServiceError(
                'unexpected response enabling service "{}": {}'.format(
                    service_name, response))

        while True:
            request = self._service_usage_service.services().get(
                name=service_name)
            response = request.execute(num_retries=5)
            # Response format:
            # https://cloud.google.com/service-usage/docs/reference/rest/v1/Service
            if response['state'] == 'ENABLED':
                return
            elif response['state'] == 'DISABLED':
                time.sleep(2)
                continue
            else:
                # In 'STATE_UNSPECIFIED' state.
                raise EnableServiceError(
                    'unexpected service status after enabling: {!r}: [{!r}]'.
                    format(response['status'], response))
Exemplo n.º 6
0
    def create_super_user(self,
                          superuser_name: str,
                          superuser_email: str,
                          superuser_password: str,
                          project_id: str,
                          instance_name: str,
                          cloud_sql_proxy_path: str = 'cloud_sql_proxy',
                          region: str = 'us-west1',
                          port: Optional[int] = 5432):
        """Create a super user in the cloud sql database.

        This function should be called after we did the following:
            1. Generated the Django project source files.
            2. Setup Django environment so that it is using configuration files
               of the newly generated project.
            3. Created the Cloud SQL instance and database user.
            4. Migrated database. Otherwise the schema for superuser does not
               exist.

        Args:
            superuser_name: Name of the super user you want to create.
            superuser_email: Email of the super user you want to create.
            superuser_password: Password of the super user you want to create.
            project_id: GCP project id.
            instance_name: The Cloud SQL instance name in which you want to
                create the super user.
            cloud_sql_proxy_path: The command to run your cloud sql proxy.
            region: Where the Cloud SQL instance is in.
            port: The port being forwarded by cloud sql proxy.
        """

        with self.with_cloud_sql_proxy(project_id, instance_name,
                                       cloud_sql_proxy_path, region, port):
            # This can only be imported after django.setup() is called
            try:
                from django.contrib.auth.models import User

                # Check whether the super user we want to create exist or not
                # If a superuser with the same name already exist, we will skip
                # creation
                users = User.objects.filter(username=superuser_name)
                for user in users:
                    if user.is_superuser:
                        return
                User.objects.create_superuser(
                    username=superuser_name,
                    email=superuser_email,
                    password=superuser_password)
            except Exception as e:
                raise crash_handling.UserError(
                    'Not able to create super user.') from e
Exemplo n.º 7
0
    def migrate_database(self,
                         project_id: str,
                         instance_name: str,
                         cloud_sql_proxy_path: str = 'cloud_sql_proxy',
                         region: str = 'us-west1',
                         port: Optional[int] = 5432):
        """Migrate to Cloud SQL database.

        This function should be called after we do the following:
            1. Generated the Django project source files.
            2. Setup Django environment so that it is using configuration files
               of the newly generated project.
            3. Created the Cloud SQL instance and database user.

        Args:
            project_id: GCP project id.
            instance_name: Name of the Cloud SQL instance where the database you
                want to migrate is in.
            cloud_sql_proxy_path: The command to run your cloud sql proxy.
            region: Where the Cloud SQL instance is in.
            port: The port being forwarded by cloud sql proxy.
        """
        with self.with_cloud_sql_proxy(project_id, instance_name,
                                       cloud_sql_proxy_path, region, port):
            try:
                # "makemigrations" will generate migration files based on
                # definitions in models.py.
                management.call_command('makemigrations',
                                        verbosity=0,
                                        interactive=False)

                # "migrate" will modify cloud sql database.
                management.call_command('migrate',
                                        verbosity=0,
                                        interactive=False)
            except Exception as e:
                raise crash_handling.UserError(
                    'Not able to migrate database.') from e