def test_production_instance_factory(self): """ Test that factory function for creating production instances produces expected results """ # Create instance without changing defaults sub_domain = "production-instance-with-defaults" instance = production_instance_factory(sub_domain=sub_domain) instance = OpenEdXInstance.objects.get(pk=instance.pk) self._assert_field_values(instance, sub_domain, **self.PRODUCTION_DEFAULTS) # Create instance with custom field values sub_domain = "production-instance-customized" custom_instance = production_instance_factory(sub_domain=sub_domain, **self.SANDBOX_DEFAULTS) custom_instance = OpenEdXInstance.objects.get(pk=custom_instance.pk) expected_settings = self.SANDBOX_DEFAULTS.copy() expected_settings["configuration_extra_settings"] = self.PRODUCTION_DEFAULTS["configuration_extra_settings"] self._assert_field_values(custom_instance, sub_domain, **expected_settings) # Create instance that overrides defaults for extra settings sub_domain = "production-instance-extra-settings" configuration_extra_settings = """ DEMO_CREATE_STAFF_USER: false demo_test_users: [] SANDBOX_ENABLE_CERTIFICATES: false EXTRA_SETTINGS: false ADDITIONAL_SETTINGS: true """ expected_settings["configuration_extra_settings"] = configuration_extra_settings extra_settings_instance = production_instance_factory(sub_domain=sub_domain, **expected_settings) extra_settings_instance = OpenEdXInstance.objects.get(pk=extra_settings_instance.pk) self._assert_field_values(extra_settings_instance, sub_domain, **expected_settings) # Calling factory without specifying "sub_domain" should result in an error with self.assertRaises(AssertionError): production_instance_factory()
def test_production_instance_factory_no_databases(self): """ Test that calling `production_instance_factory` with settings that are problematic for production instances produces warnings and does not create production instance. """ # Delete database server objects created during the migrations. MySQLServer.objects.all().delete() MongoDBServer.objects.all().delete() for custom_settings, warning in ( ( { 'INSTANCE_STORAGE_TYPE': StorageContainer.S3_STORAGE, 'AWS_ACCESS_KEY': None, 'AWS_SECRET_ACCESS_KEY': None }, ( "AWS support is currently enabled. Add AWS_ACCESS_KEY_ID and " "AWS_SECRET_ACCESS_KEY settings or adjust INSTANCE_STORAGE_TYPE setting." ), ), ( {'DEFAULT_INSTANCE_MYSQL_URL': None}, ( "No MySQL servers configured, and default URL for external MySQL database is missing." "Create at least one MySQLServer, or set DEFAULT_INSTANCE_MYSQL_URL in your .env." ), ), ( {'DEFAULT_INSTANCE_MONGO_URL': None}, ( "No MongoDB servers configured, and default URL for external MongoDB database is missing." "Create at least one MongoDBServer, or set DEFAULT_INSTANCE_MONGO_URL in your .env." ), ), ): with override_settings(**custom_settings): sub_domain = "production-instance-doomed" production_instance_factory(sub_domain=sub_domain) log_entries = LogEntry.objects.filter(level="WARNING") general_entry = log_entries[0] setting_entry = log_entries[1] self.assertIn( "Environment not ready. Please fix the problems above, then try again. Aborting.", general_entry.text ) self.assertIn(warning, setting_entry.text) self.assertFalse( OpenEdXInstance.objects.filter(internal_lms_domain__startswith=sub_domain).exists() )
def test_production_instance_factory(self, patched_loader): """ Test that factory function for creating production instances produces expected results """ mock_template = Mock() mock_template.render.return_value = self.CONFIGURATION_EXTRA_SETTINGS patched_loader.get_template.return_value = mock_template # Create instance without changing defaults sub_domain = "production-instance-with-defaults" instance = production_instance_factory(sub_domain=sub_domain) instance = OpenEdXInstance.objects.get(pk=instance.pk) self._assert_field_values(instance, sub_domain, **self.PRODUCTION_DEFAULTS) patched_loader.get_template.assert_called_once_with( "instance/ansible/prod-vars.yml") mock_template.render.assert_called_once_with({}) # Create instance with custom field values sub_domain = "production-instance-customized" custom_instance = production_instance_factory(sub_domain=sub_domain, **self.SANDBOX_DEFAULTS) custom_instance = OpenEdXInstance.objects.get(pk=custom_instance.pk) expected_settings = self.SANDBOX_DEFAULTS.copy() expected_settings[ "configuration_extra_settings"] = self.PRODUCTION_DEFAULTS[ "configuration_extra_settings"] self._assert_field_values(custom_instance, sub_domain, **expected_settings) # Create instance that overrides defaults for extra settings sub_domain = "production-instance-extra-settings" configuration_extra_settings = """ EXTRA_SETTINGS: false ADDITIONAL_SETTINGS: true """ expected_settings[ "configuration_extra_settings"] = configuration_extra_settings extra_settings_instance = production_instance_factory( sub_domain=sub_domain, **expected_settings) extra_settings_instance = OpenEdXInstance.objects.get( pk=extra_settings_instance.pk) self._assert_field_values(extra_settings_instance, sub_domain, **expected_settings) # Calling factory without specifying "sub_domain" should result in an error with self.assertRaises(AssertionError): production_instance_factory()
def _provision_instance(sender, **kwargs): """Provision a new instance once all email addresses of a user are confirmed.""" user = sender if not all(email.is_confirmed for email in user.email_address_set.iterator()): return try: application = user.betatestapplication except BetaTestApplication.DoesNotExist: logger.info('Email confirmed for user %s, who is not a beta tester.', user.username) return if application.status == BetaTestApplication.REJECTED: logger.info('Email confirmed for user %s, but application was rejected.', user.username) return if application.instance is not None: logger.info('Email confirmed for user %s, but instance already provisioned.', user.username) return with transaction.atomic(): application.instance = production_instance_factory( sub_domain=application.subdomain, name=application.instance_name, email=application.public_contact_email, deploy_simpletheme=True, ) application.instance.lms_users.add(user) application.save() spawn_appserver(application.instance.ref.pk, mark_active_on_success=True, num_attempts=2)
def _provision_instance(sender, **kwargs): """Provision a new instance once all email addresses of a user are confirmed.""" user = sender if not all(email.is_confirmed for email in user.email_address_set.iterator()): return try: application = user.betatestapplication except BetaTestApplication.DoesNotExist: logger.info('Email confirmed for user %s, who is not a beta tester.', user.username) return if application.status == BetaTestApplication.REJECTED: logger.info('Email confirmed for user %s, but application was rejected.', user.username) return if application.instance is not None: logger.info('Email confirmed for user %s, but instance already provisioned.', user.username) return with transaction.atomic(): application.instance = production_instance_factory( sub_domain=application.subdomain, name=application.instance_name, email=application.public_contact_email, ) application.instance.lms_users.add(user) application.save() spawn_appserver(application.instance.ref.pk, mark_active_on_success=True, num_attempts=2)
def _provision_instance(sender, **kwargs): """Provision a new instance once all email addresses of a user are confirmed.""" user = sender if not all(email.is_confirmed for email in user.email_address_set.iterator()): return try: application = user.betatestapplication except BetaTestApplication.DoesNotExist: logger.info('Email confirmed for user %s, who is not a beta tester.', user.username) return if application.status == BetaTestApplication.REJECTED: logger.info('Email confirmed for user %s, but application was rejected.', user.username) return if application.instance is not None: logger.info('Email confirmed for user %s, but instance already provisioned.', user.username) return with transaction.atomic(): application.instance = production_instance_factory( sub_domain=application.subdomain, name=application.instance_name, email=application.public_contact_email, privacy_policy_url=application.privacy_policy_url, deploy_simpletheme=True, ) application.instance.lms_users.add(user) if settings.PROD_APPSERVER_FAIL_EMAILS: application.instance.provisioning_failure_notification_emails = settings.PROD_APPSERVER_FAIL_EMAILS application.instance.save() application.save() # At this point we know the user has confirmed their email and set up an instance. # So we can go ahead and send the account info email. transaction.on_commit(lambda: send_account_info_email(application)) spawn_appserver(application.instance.ref.pk, mark_active_on_success=True, num_attempts=2)
def test_production_instance_factory_no_databases(self): """ Test that calling `production_instance_factory` with settings that are problematic for production instances produces warnings and does not create production instance. """ # Delete database server objects created during the migrations. MySQLServer.objects.all().delete() MongoDBServer.objects.all().delete() for setting, value, warning in ( ( 'SWIFT_ENABLE', False, 'Swift support is currently disabled. Adjust SWIFT_ENABLE setting.', ), ( 'DEFAULT_INSTANCE_MYSQL_URL', None, ("No MySQL servers configured, and default URL for external MySQL database is missing." "Create at least one MySQLServer, or set DEFAULT_INSTANCE_MYSQL_URL in your .env." ), ), ( 'DEFAULT_INSTANCE_MONGO_URL', None, ("No MongoDB servers configured, and default URL for external MongoDB database is missing." "Create at least one MongoDBServer, or set DEFAULT_INSTANCE_MONGO_URL in your .env." ), ), ): with override_settings(**{setting: value}): sub_domain = "production-instance-doomed" production_instance_factory(sub_domain=sub_domain) log_entries = LogEntry.objects.filter(level="WARNING") general_entry = log_entries[0] setting_entry = log_entries[1] self.assertIn( "Environment not ready. Please fix the problems above, then try again. Aborting.", general_entry.text) self.assertIn(warning, setting_entry.text) self.assertFalse( OpenEdXInstance.objects.filter( internal_lms_domain__startswith=sub_domain).exists())
def test_production_instance_factory_no_databases(self): """ Test that calling `production_instance_factory` with settings that are problematic for production instances produces warnings and does not create production instance. """ for setting, value, warning in ( ("SWIFT_ENABLE", False, "Swift support is currently disabled. Adjust SWIFT_ENABLE setting."), ( "DEFAULT_INSTANCE_MYSQL_URL", None, ( "No MySQL servers configured, and default URL for external MySQL database is missing." "Create at least one MySQLServer, or set DEFAULT_INSTANCE_MYSQL_URL in your .env." ), ), ( "DEFAULT_INSTANCE_MONGO_URL", None, ( "No MongoDB servers configured, and default URL for external MongoDB database is missing." "Create at least one MongoDBServer, or set DEFAULT_INSTANCE_MONGO_URL in your .env." ), ), ): with patch("instance.factories.settings") as patched_settings: setattr(patched_settings, setting, value) sub_domain = "production-instance-doomed" production_instance_factory(sub_domain=sub_domain) log_entries = LogEntry.objects.all() general_entry = log_entries[0] setting_entry = log_entries[1] for log_entry in (general_entry, setting_entry): self.assertEqual(log_entry.level, "WARNING") self.assertIn( "Environment not ready. Please fix the problems above, then try again. Aborting.", general_entry.text, ) self.assertIn(warning, setting_entry.text) self.assertFalse(OpenEdXInstance.objects.filter(internal_lms_domain__startswith=sub_domain).exists())
def test_production_instance_factory(self, patched_loader): """ Test that factory function for creating production instances produces expected results """ mock_template = Mock() mock_template.render.return_value = self.CONFIGURATION_EXTRA_SETTINGS patched_loader.get_template.return_value = mock_template # Create instance without changing defaults sub_domain = "production-instance-with-defaults" instance = production_instance_factory(sub_domain=sub_domain) instance = OpenEdXInstance.objects.get(pk=instance.pk) self._assert_field_values(instance, sub_domain, **self.PRODUCTION_DEFAULTS) patched_loader.get_template.assert_called_once_with("instance/ansible/prod-vars.yml") mock_template.render.assert_called_once_with({}) # Create instance with custom field values sub_domain = "production-instance-customized" custom_instance = production_instance_factory(sub_domain=sub_domain, **self.SANDBOX_DEFAULTS) custom_instance = OpenEdXInstance.objects.get(pk=custom_instance.pk) expected_settings = self.SANDBOX_DEFAULTS.copy() expected_settings["configuration_extra_settings"] = self.PRODUCTION_DEFAULTS["configuration_extra_settings"] self._assert_field_values(custom_instance, sub_domain, **expected_settings) # Create instance that overrides defaults for extra settings sub_domain = "production-instance-extra-settings" configuration_extra_settings = """ EXTRA_SETTINGS: false ADDITIONAL_SETTINGS: true """ expected_settings["configuration_extra_settings"] = configuration_extra_settings extra_settings_instance = production_instance_factory(sub_domain=sub_domain, **expected_settings) extra_settings_instance = OpenEdXInstance.objects.get(pk=extra_settings_instance.pk) self._assert_field_values(extra_settings_instance, sub_domain, **expected_settings) # Calling factory without specifying "sub_domain" should result in an error with self.assertRaises(AssertionError): production_instance_factory()