def get_cluster_from_options(backend, options, cluster_manager=clusters): cluster_option_name = 'cluster' default_cluster_name = 'default' cluster_constructor_option_names = frozenset(('hosts',)) options = options.copy() cluster_options = {key: options.pop(key) for key in set(options.keys()).intersection(cluster_constructor_option_names)} if cluster_options: if cluster_option_name in options: raise InvalidConfiguration( 'Cannot provide both named cluster ({!r}) and cluster configuration ({}) options.'.format( cluster_option_name, ', '.join(map(repr, cluster_constructor_option_names)), ) ) else: warnings.warn( 'Providing Redis cluster configuration options ({}) to {!r} is ' 'deprecated, please update your configuration to use named Redis ' 'clusters ({!r}).'.format( ', '.join(map(repr, cluster_constructor_option_names)), backend, cluster_option_name, ), DeprecationWarning, stacklevel=2 ) cluster = rb.Cluster(pool_cls=_shared_pool, **cluster_options) else: cluster = cluster_manager.get(options.pop(cluster_option_name, default_cluster_name)) return cluster, options
def check_versions(service, versions, required, recommended=None): """ Check that hosts fulfill version requirements. :param service: service label, such as ``Redis`` :param versions: mapping of host to ``Version`` :param required: lowest supported ``Version``. If any host does not fulfill this requirement, an ``InvalidConfiguration`` exception is raised. :param recommended: recommended version. If any host does not fulfill this requirement, a ``PendingDeprecationWarning`` is raised. """ # x = (host, version) must_upgrade = dict([x for x in versions.items() if required > x[1]]) if must_upgrade: raise InvalidConfiguration( make_upgrade_message(service, "must", required, must_upgrade)) if recommended: # x = (host, version) should_upgrade = dict( [x for x in versions.items() if recommended > x[1]]) if should_upgrade: warnings.warn( make_upgrade_message(service, "should", recommended, should_upgrade), PendingDeprecationWarning, )
def get_cluster_from_options(setting, options, cluster_manager=clusters): cluster_option_name = 'cluster' default_cluster_name = 'default' cluster_constructor_option_names = frozenset(('hosts',)) options = options.copy() cluster_options = {key: options.pop(key) for key in set(options.keys()).intersection(cluster_constructor_option_names)} if cluster_options: if cluster_option_name in options: raise InvalidConfiguration( 'Cannot provide both named cluster ({!r}) and cluster configuration ({}) options.'.format( cluster_option_name, ', '.join(map(repr, cluster_constructor_option_names)), ) ) else: warnings.warn( DeprecatedSettingWarning( '{} parameter of {}'.format( ', '.join(map(repr, cluster_constructor_option_names)), setting, ), '{}["{}"]'.format( setting, cluster_option_name, ), removed_in_version='8.5', ), stacklevel=2 ) cluster = rb.Cluster(pool_cls=_shared_pool, **cluster_options) else: cluster = cluster_manager.get(options.pop(cluster_option_name, default_cluster_name)) return cluster, options
def initialize_app(config, skip_service_validation=False): settings = config['settings'] bootstrap_options(settings, config['options']) configure_structlog() if 'south' in settings.INSTALLED_APPS: fix_south(settings) apply_legacy_settings(settings) bind_cache_to_option_store() # Commonly setups don't correctly configure themselves for production envs # so lets try to provide a bit more guidance if settings.CELERY_ALWAYS_EAGER and not settings.DEBUG: warnings.warn( 'Sentry is configured to run asynchronous tasks in-process. ' 'This is not recommended within production environments. ' 'See https://docs.sentry.io/on-premise/server/queue/ for more information.' ) if settings.SENTRY_SINGLE_ORGANIZATION: settings.SENTRY_FEATURES['organizations:create'] = False if not hasattr(settings, 'SUDO_COOKIE_SECURE'): settings.SUDO_COOKIE_SECURE = getattr(settings, 'SESSION_COOKIE_SECURE', False) if not hasattr(settings, 'SUDO_COOKIE_DOMAIN'): settings.SUDO_COOKIE_DOMAIN = getattr(settings, 'SESSION_COOKIE_DOMAIN', None) if not hasattr(settings, 'SUDO_COOKIE_PATH'): settings.SUDO_COOKIE_PATH = getattr(settings, 'SESSION_COOKIE_PATH', '/') if not hasattr(settings, 'CSRF_COOKIE_SECURE'): settings.CSRF_COOKIE_SECURE = getattr(settings, 'SESSION_COOKIE_SECURE', False) if not hasattr(settings, 'CSRF_COOKIE_DOMAIN'): settings.CSRF_COOKIE_DOMAIN = getattr(settings, 'SESSION_COOKIE_DOMAIN', None) if not hasattr(settings, 'CSRF_COOKIE_PATH'): settings.CSRF_COOKIE_PATH = getattr(settings, 'SESSION_COOKIE_PATH', '/') settings.CACHES['default']['VERSION'] = settings.CACHE_VERSION settings.ASSET_VERSION = get_asset_version(settings) settings.STATIC_URL = settings.STATIC_URL.format( version=settings.ASSET_VERSION, ) register_plugins(settings) initialize_receivers() validate_options(settings) setup_services(validate=not skip_service_validation) from django.utils import timezone from sentry.app import env from sentry.runner.settings import get_sentry_conf env.data['config'] = get_sentry_conf() env.data['start_date'] = timezone.now()
def bootstrap_options(settings, config=None): """ Quickly bootstrap options that come in from a config file and convert options into Django settings that are required to even initialize the rest of the app. """ # Make sure our options have gotten registered from sentry.options import load_defaults load_defaults() options = {} if config is not None: # Attempt to load our config yaml file from sentry.utils.yaml import safe_load from yaml.parser import ParserError from yaml.scanner import ScannerError try: with open(config, 'rb') as fp: options = safe_load(fp) except IOError: # Gracefully fail if yaml file doesn't exist pass except (AttributeError, ParserError, ScannerError) as e: from .importer import ConfigurationError raise ConfigurationError('Malformed config.yml file: %s' % unicode(e)) # Empty options file, so fail gracefully if options is None: options = {} # Options needs to be a dict elif not isinstance(options, dict): from .importer import ConfigurationError raise ConfigurationError('Malformed config.yml file') from sentry.conf.server import DEAD # First move options from settings into options for k, v in options_mapper.iteritems(): if getattr(settings, v, DEAD) is not DEAD and k not in options: warnings.warn( DeprecatedSettingWarning( options_mapper[k], "SENTRY_OPTIONS['%s']" % k, ) ) options[k] = getattr(settings, v) # Stuff everything else into SENTRY_OPTIONS # these will be validated later after bootstrapping for k, v in options.iteritems(): settings.SENTRY_OPTIONS[k] = v # Now go back through all of SENTRY_OPTIONS and promote # back into settings. This catches the case when values are defined # only in SENTRY_OPTIONS and no config.yml file for o in (settings.SENTRY_DEFAULT_OPTIONS, settings.SENTRY_OPTIONS): for k, v in o.iteritems(): if k in options_mapper: # Escalate the few needed to actually get the app bootstrapped into settings setattr(settings, options_mapper[k], v)
def get_cluster_from_options(setting, options, cluster_manager=clusters): cluster_option_name = "cluster" default_cluster_name = "default" cluster_constructor_option_names = frozenset(("hosts",)) options = options.copy() cluster_options = { key: options.pop(key) for key in set(options.keys()).intersection(cluster_constructor_option_names) } if cluster_options: if cluster_option_name in options: raise InvalidConfiguration( "Cannot provide both named cluster ({!r}) and cluster configuration ({}) options.".format( cluster_option_name, ", ".join(map(repr, cluster_constructor_option_names)) ) ) else: warnings.warn( DeprecatedSettingWarning( "{} parameter of {}".format( ", ".join(map(repr, cluster_constructor_option_names)), setting ), f'{setting}["{cluster_option_name}"]', removed_in_version="8.5", ), stacklevel=2, ) cluster = rb.Cluster(pool_cls=_shared_pool, **cluster_options) else: cluster = cluster_manager.get(options.pop(cluster_option_name, default_cluster_name)) return cluster, options
def initialize_app(config, skip_backend_validation=False): settings = config['settings'] bootstrap_options(settings, config['options']) configure_structlog() fix_south(settings) apply_legacy_settings(settings) bind_cache_to_option_store() install_plugin_apps(settings) # Commonly setups don't correctly configure themselves for production envs # so lets try to provide a bit more guidance if settings.CELERY_ALWAYS_EAGER and not settings.DEBUG: warnings.warn( 'Sentry is configured to run asynchronous tasks in-process. ' 'This is not recommended within production environments. ' 'See https://docs.getsentry.com/on-premise/server/queue/ for more information.' ) if settings.SENTRY_SINGLE_ORGANIZATION: settings.SENTRY_FEATURES['organizations:create'] = False settings.SUDO_COOKIE_SECURE = getattr(settings, 'SESSION_COOKIE_SECURE', False) settings.SUDO_COOKIE_DOMAIN = getattr(settings, 'SESSION_COOKIE_DOMAIN', None) settings.SUDO_COOKIE_PATH = getattr(settings, 'SESSION_COOKIE_PATH', '/') settings.CSRF_COOKIE_SECURE = getattr(settings, 'SESSION_COOKIE_SECURE', False) settings.CSRF_COOKIE_DOMAIN = getattr(settings, 'SESSION_COOKIE_DOMAIN', None) settings.CSRF_COOKIE_PATH = getattr(settings, 'SESSION_COOKIE_PATH', '/') settings.CACHES['default']['VERSION'] = settings.CACHE_VERSION settings.ASSET_VERSION = get_asset_version(settings) settings.STATIC_URL = settings.STATIC_URL.format( version=settings.ASSET_VERSION, ) register_plugins(settings) initialize_receivers() validate_options(settings) if not skip_backend_validation: validate_backends() from django.utils import timezone from sentry.app import env from sentry.runner.settings import get_sentry_conf env.data['config'] = get_sentry_conf() env.data['start_date'] = timezone.now()
def _setup(self): backend = import_string(self._backend) if backend in self._dangerous: warnings.warn( warnings.UnsupportedBackend( u'The {!r} backend for {} is not recommended ' 'for production use.'.format(self._backend, self._base))) instance = backend(**self._options) self._wrapped = instance
def make_rb_cluster(*args, **kwargs): # This uses the standard library `warnings`, since this is provided for # plugin compatibility but isn't actionable by the system administrator. import warnings warnings.warn( 'Direct Redis cluster construction is deprecated, please use named clusters.', DeprecationWarning, ) return _make_rb_cluster(*args, **kwargs)
def _setup(self): backend = import_string(self._backend) assert issubclass(backend, Service) if backend in self._dangerous: warnings.warn( warnings.UnsupportedBackend( u"The {!r} backend for {} is not recommended " "for production use.".format(self._backend, self._base))) instance = backend(**self._options) self._wrapped = instance
def make_rb_cluster(*args, **kwargs): # This uses the standard library `warnings`, since this is provided for # plugin compatibility but isn't actionable by the system administrator. import warnings warnings.warn( 'Direct Redis cluster construction is deprecated, please use named clusters. ' 'Direct cluster construction will be removed in Sentry 8.5.', DeprecationWarning, ) return _make_rb_cluster(*args, **kwargs)
def get_instance(attribute, options, dangerous=()): value = getattr(settings, attribute) cls = import_string(value) if cls in dangerous: warnings.warn( warnings.UnsupportedBackend( u'The {!r} backend for {} is not recommended ' 'for production use.'.format(value, attribute))) return cls(**options)
def _setup(self): backend = import_string(self._backend) if backend in self._dangerous: warnings.warn( warnings.UnsupportedBackend( u'The {!r} backend for {} is not recommended ' 'for production use.'.format(self._backend, self._base) ) ) instance = backend(**self._options) self._wrapped = instance
def initialize_app(config, skip_backend_validation=False): settings = config["settings"] bootstrap_options(settings, config["options"]) fix_south(settings) apply_legacy_settings(settings) bind_cache_to_option_store() install_plugin_apps(settings) # Commonly setups don't correctly configure themselves for production envs # so lets try to provide a bit more guidance if settings.CELERY_ALWAYS_EAGER and not settings.DEBUG: warnings.warn( "Sentry is configured to run asynchronous tasks in-process. " "This is not recommended within production environments. " "See https://docs.getsentry.com/on-premise/server/queue/ for more information." ) if settings.SENTRY_SINGLE_ORGANIZATION: settings.SENTRY_FEATURES["organizations:create"] = False settings.SUDO_COOKIE_SECURE = getattr(settings, "SESSION_COOKIE_SECURE", False) settings.SUDO_COOKIE_DOMAIN = getattr(settings, "SESSION_COOKIE_DOMAIN", None) settings.SUDO_COOKIE_PATH = getattr(settings, "SESSION_COOKIE_PATH", "/") settings.CSRF_COOKIE_SECURE = getattr(settings, "SESSION_COOKIE_SECURE", False) settings.CSRF_COOKIE_DOMAIN = getattr(settings, "SESSION_COOKIE_DOMAIN", None) settings.CSRF_COOKIE_PATH = getattr(settings, "SESSION_COOKIE_PATH", "/") settings.CACHES["default"]["VERSION"] = settings.CACHE_VERSION settings.ASSET_VERSION = get_asset_version(settings) settings.STATIC_URL = settings.STATIC_URL.format(version=settings.ASSET_VERSION) register_plugins(settings) initialize_receivers() validate_options(settings) if not skip_backend_validation: validate_backends() from django.utils import timezone from sentry.app import env from sentry.runner.settings import get_sentry_conf env.data["config"] = get_sentry_conf() env.data["start_date"] = timezone.now()
def get_instance(attribute, options, dangerous=()): value = getattr(settings, attribute) cls = import_string(value) if cls in dangerous: warnings.warn( warnings.UnsupportedBackend( u'The {!r} backend for {} is not recommended ' 'for production use.'.format(value, attribute) ) ) return cls(**options)
def check_versions(service, versions, required, recommended=None): """ Check that hosts fulfill version requirements. :param service: service label, such as ``Redis`` :param versions: mapping of host to ``Version`` :param required: lowest supported ``Version``. If any host does not fulfill this requirement, an ``InvalidConfiguration`` exception is raised. :param recommended: recommended version. If any host does not fulfill this requirement, a ``PendingDeprecationWarning`` is raised. """ must_upgrade = dict(filter(lambda (host, version): required > version, versions.items())) if must_upgrade: raise InvalidConfiguration(make_upgrade_message(service, 'must', required, must_upgrade)) if recommended: should_upgrade = dict(filter(lambda (host, version): recommended > version, versions.items())) if should_upgrade: warnings.warn( make_upgrade_message(service, 'should', recommended, should_upgrade), PendingDeprecationWarning, )
def apply_legacy_settings(settings): from sentry import options # SENTRY_USE_QUEUE used to determine if Celery was eager or not if hasattr(settings, 'SENTRY_USE_QUEUE'): warnings.warn( DeprecatedSettingWarning( 'SENTRY_USE_QUEUE', 'CELERY_ALWAYS_EAGER', 'https://docs.sentry.io/on-premise/server/queue/', )) settings.CELERY_ALWAYS_EAGER = (not settings.SENTRY_USE_QUEUE) for old, new in ( ('SENTRY_ADMIN_EMAIL', 'system.admin-email'), ('SENTRY_URL_PREFIX', 'system.url-prefix'), ('SENTRY_SYSTEM_MAX_EVENTS_PER_MINUTE', 'system.rate-limit'), ('SENTRY_ENABLE_EMAIL_REPLIES', 'mail.enable-replies'), ('SENTRY_SMTP_HOSTNAME', 'mail.reply-hostname'), ('MAILGUN_API_KEY', 'mail.mailgun-api-key'), ): if new not in settings.SENTRY_OPTIONS and hasattr(settings, old): warnings.warn( DeprecatedSettingWarning(old, "SENTRY_OPTIONS['%s']" % new)) settings.SENTRY_OPTIONS[new] = getattr(settings, old) if hasattr(settings, 'SENTRY_REDIS_OPTIONS'): if 'redis.clusters' in settings.SENTRY_OPTIONS: raise Exception( "Cannot specify both SENTRY_OPTIONS['redis.clusters'] option and SENTRY_REDIS_OPTIONS setting." ) else: warnings.warn( DeprecatedSettingWarning( 'SENTRY_REDIS_OPTIONS', 'SENTRY_OPTIONS["redis.clusters"]', removed_in_version='8.5', )) settings.SENTRY_OPTIONS['redis.clusters'] = { 'default': settings.SENTRY_REDIS_OPTIONS, } else: # Provide backwards compatibility to plugins expecting there to be a # ``SENTRY_REDIS_OPTIONS`` setting by using the ``default`` cluster. # This should be removed when ``SENTRY_REDIS_OPTIONS`` is officially # deprecated. (This also assumes ``FLAG_NOSTORE`` on the configuration # option.) settings.SENTRY_REDIS_OPTIONS = options.get( 'redis.clusters')['default'] if not hasattr(settings, 'SENTRY_URL_PREFIX'): url_prefix = options.get('system.url-prefix', silent=True) if not url_prefix: # HACK: We need to have some value here for backwards compatibility url_prefix = 'http://sentry.example.com' settings.SENTRY_URL_PREFIX = url_prefix if settings.TIME_ZONE != 'UTC': # non-UTC timezones are not supported show_big_error('TIME_ZONE should be set to UTC') # Set ALLOWED_HOSTS if it's not already available if not settings.ALLOWED_HOSTS: settings.ALLOWED_HOSTS = ['*'] if hasattr(settings, 'SENTRY_ALLOW_REGISTRATION'): warnings.warn( DeprecatedSettingWarning('SENTRY_ALLOW_REGISTRATION', 'SENTRY_FEATURES["auth:register"]')) settings.SENTRY_FEATURES[ 'auth:register'] = settings.SENTRY_ALLOW_REGISTRATION settings.DEFAULT_FROM_EMAIL = settings.SENTRY_OPTIONS.get( 'mail.from', settings.SENTRY_DEFAULT_OPTIONS.get('mail.from')) # HACK(mattrobenolt): This is a one-off assertion for a system.secret-key value. # If this becomes a pattern, we could add another flag to the OptionsManager to cover this, but for now # this is the only value that should prevent the app from booting up. Currently FLAG_REQUIRED is used to # trigger the Installation Wizard, not abort startup. if not settings.SENTRY_OPTIONS.get('system.secret-key'): from .importer import ConfigurationError raise ConfigurationError( "`system.secret-key` MUST be set. Use 'sentry config generate-secret-key' to get one." )
def apply_legacy_settings(settings): from sentry import options # SENTRY_USE_QUEUE used to determine if Celery was eager or not if hasattr(settings, "SENTRY_USE_QUEUE"): warnings.warn( DeprecatedSettingWarning( "SENTRY_USE_QUEUE", "CELERY_ALWAYS_EAGER", "https://docs.sentry.io/on-premise/server/queue/", ) ) settings.CELERY_ALWAYS_EAGER = not settings.SENTRY_USE_QUEUE for old, new in ( ("SENTRY_ADMIN_EMAIL", "system.admin-email"), ("SENTRY_URL_PREFIX", "system.url-prefix"), ("SENTRY_SYSTEM_MAX_EVENTS_PER_MINUTE", "system.rate-limit"), ("SENTRY_ENABLE_EMAIL_REPLIES", "mail.enable-replies"), ("SENTRY_SMTP_HOSTNAME", "mail.reply-hostname"), ("MAILGUN_API_KEY", "mail.mailgun-api-key"), ("SENTRY_FILESTORE", "filestore.backend"), ("SENTRY_FILESTORE_OPTIONS", "filestore.options"), ("GOOGLE_CLIENT_ID", "auth-google.client-id"), ("GOOGLE_CLIENT_SECRET", "auth-google.client-secret"), ): if new not in settings.SENTRY_OPTIONS and hasattr(settings, old): warnings.warn(DeprecatedSettingWarning(old, "SENTRY_OPTIONS['%s']" % new)) settings.SENTRY_OPTIONS[new] = getattr(settings, old) if hasattr(settings, "SENTRY_REDIS_OPTIONS"): if "redis.clusters" in settings.SENTRY_OPTIONS: raise Exception( "Cannot specify both SENTRY_OPTIONS['redis.clusters'] option and SENTRY_REDIS_OPTIONS setting." ) else: warnings.warn( DeprecatedSettingWarning( "SENTRY_REDIS_OPTIONS", 'SENTRY_OPTIONS["redis.clusters"]', removed_in_version="8.5", ) ) settings.SENTRY_OPTIONS["redis.clusters"] = {"default": settings.SENTRY_REDIS_OPTIONS} else: # Provide backwards compatibility to plugins expecting there to be a # ``SENTRY_REDIS_OPTIONS`` setting by using the ``default`` cluster. # This should be removed when ``SENTRY_REDIS_OPTIONS`` is officially # deprecated. (This also assumes ``FLAG_NOSTORE`` on the configuration # option.) settings.SENTRY_REDIS_OPTIONS = options.get("redis.clusters")["default"] if not hasattr(settings, "SENTRY_URL_PREFIX"): url_prefix = options.get("system.url-prefix", silent=True) if not url_prefix: # HACK: We need to have some value here for backwards compatibility url_prefix = "http://sentry.example.com" settings.SENTRY_URL_PREFIX = url_prefix if settings.TIME_ZONE != "UTC": # non-UTC timezones are not supported show_big_error("TIME_ZONE should be set to UTC") # Set ALLOWED_HOSTS if it's not already available if not settings.ALLOWED_HOSTS: settings.ALLOWED_HOSTS = ["*"] if hasattr(settings, "SENTRY_ALLOW_REGISTRATION"): warnings.warn( DeprecatedSettingWarning( "SENTRY_ALLOW_REGISTRATION", 'SENTRY_FEATURES["auth:register"]' ) ) settings.SENTRY_FEATURES["auth:register"] = settings.SENTRY_ALLOW_REGISTRATION settings.DEFAULT_FROM_EMAIL = settings.SENTRY_OPTIONS.get( "mail.from", settings.SENTRY_DEFAULT_OPTIONS.get("mail.from") ) # HACK(mattrobenolt): This is a one-off assertion for a system.secret-key value. # If this becomes a pattern, we could add another flag to the OptionsManager to cover this, but for now # this is the only value that should prevent the app from booting up. Currently FLAG_REQUIRED is used to # trigger the Installation Wizard, not abort startup. if not settings.SENTRY_OPTIONS.get("system.secret-key"): from .importer import ConfigurationError raise ConfigurationError( "`system.secret-key` MUST be set. Use 'sentry config generate-secret-key' to get one." )
def initialize_app(config, skip_service_validation=False): settings = config["settings"] bootstrap_options(settings, config["options"]) configure_structlog() # Commonly setups don't correctly configure themselves for production envs # so lets try to provide a bit more guidance if settings.CELERY_ALWAYS_EAGER and not settings.DEBUG: warnings.warn( "Sentry is configured to run asynchronous tasks in-process. " "This is not recommended within production environments. " "See https://docs.sentry.io/on-premise/server/queue/ for more information." ) if settings.SENTRY_SINGLE_ORGANIZATION: settings.SENTRY_FEATURES["organizations:create"] = False if not hasattr(settings, "SUDO_COOKIE_SECURE"): settings.SUDO_COOKIE_SECURE = getattr(settings, "SESSION_COOKIE_SECURE", False) if not hasattr(settings, "SUDO_COOKIE_DOMAIN"): settings.SUDO_COOKIE_DOMAIN = getattr(settings, "SESSION_COOKIE_DOMAIN", None) if not hasattr(settings, "SUDO_COOKIE_PATH"): settings.SUDO_COOKIE_PATH = getattr(settings, "SESSION_COOKIE_PATH", "/") if not hasattr(settings, "CSRF_COOKIE_SECURE"): settings.CSRF_COOKIE_SECURE = getattr(settings, "SESSION_COOKIE_SECURE", False) if not hasattr(settings, "CSRF_COOKIE_DOMAIN"): settings.CSRF_COOKIE_DOMAIN = getattr(settings, "SESSION_COOKIE_DOMAIN", None) if not hasattr(settings, "CSRF_COOKIE_PATH"): settings.CSRF_COOKIE_PATH = getattr(settings, "SESSION_COOKIE_PATH", "/") settings.CACHES["default"]["VERSION"] = settings.CACHE_VERSION settings.ASSET_VERSION = get_asset_version(settings) settings.STATIC_URL = settings.STATIC_URL.format(version=settings.ASSET_VERSION) if getattr(settings, "SENTRY_DEBUGGER", None) is None: settings.SENTRY_DEBUGGER = settings.DEBUG monkeypatch_model_unpickle() import django django.setup() monkeypatch_django_migrations() apply_legacy_settings(settings) bind_cache_to_option_store() register_plugins(settings) initialize_receivers() validate_options(settings) validate_snuba() configure_sdk() setup_services(validate=not skip_service_validation) from django.utils import timezone from sentry.app import env from sentry.runner.settings import get_sentry_conf env.data["config"] = get_sentry_conf() env.data["start_date"] = timezone.now()
def bootstrap_options(settings, config=None): """ Quickly bootstrap options that come in from a config file and convert options into Django settings that are required to even initialize the rest of the app. """ # Make sure our options have gotten registered from sentry.options import load_defaults load_defaults() options = {} if config is not None: # Attempt to load our config yaml file from sentry.utils.yaml import safe_load from yaml.parser import ParserError from yaml.scanner import ScannerError try: with open(config, "rb") as fp: options = safe_load(fp) except IOError: # Gracefully fail if yaml file doesn't exist pass except (AttributeError, ParserError, ScannerError) as e: from .importer import ConfigurationError raise ConfigurationError("Malformed config.yml file: %s" % six.text_type(e)) # Empty options file, so fail gracefully if options is None: options = {} # Options needs to be a dict elif not isinstance(options, dict): from .importer import ConfigurationError raise ConfigurationError("Malformed config.yml file") from sentry.conf.server import DEAD # First move options from settings into options for k, v in six.iteritems(options_mapper): if getattr(settings, v, DEAD) is not DEAD and k not in options: warnings.warn(DeprecatedSettingWarning(options_mapper[k], "SENTRY_OPTIONS['%s']" % k)) options[k] = getattr(settings, v) # Stuff everything else into SENTRY_OPTIONS # these will be validated later after bootstrapping for k, v in six.iteritems(options): settings.SENTRY_OPTIONS[k] = v # Now go back through all of SENTRY_OPTIONS and promote # back into settings. This catches the case when values are defined # only in SENTRY_OPTIONS and no config.yml file for o in (settings.SENTRY_DEFAULT_OPTIONS, settings.SENTRY_OPTIONS): for k, v in six.iteritems(o): if k in options_mapper: # Map the mail.backend aliases to something Django understands if k == "mail.backend": try: v = settings.SENTRY_EMAIL_BACKEND_ALIASES[v] except KeyError: pass # Escalate the few needed to actually get the app bootstrapped into settings setattr(settings, options_mapper[k], v)
def apply_legacy_settings(settings): from sentry import options # SENTRY_USE_QUEUE used to determine if Celery was eager or not if hasattr(settings, 'SENTRY_USE_QUEUE'): warnings.warn( DeprecatedSettingWarning( 'SENTRY_USE_QUEUE', 'CELERY_ALWAYS_EAGER', 'https://docs.sentry.io/on-premise/server/queue/', ) ) settings.CELERY_ALWAYS_EAGER = (not settings.SENTRY_USE_QUEUE) for old, new in ( ('SENTRY_ADMIN_EMAIL', 'system.admin-email'), ('SENTRY_URL_PREFIX', 'system.url-prefix'), ('SENTRY_SYSTEM_MAX_EVENTS_PER_MINUTE', 'system.rate-limit'), ('SENTRY_ENABLE_EMAIL_REPLIES', 'mail.enable-replies'), ('SENTRY_SMTP_HOSTNAME', 'mail.reply-hostname'), ('MAILGUN_API_KEY', 'mail.mailgun-api-key'), ('SENTRY_FILESTORE', 'filestore.backend'), ('SENTRY_FILESTORE_OPTIONS', 'filestore.options'), ): if new not in settings.SENTRY_OPTIONS and hasattr(settings, old): warnings.warn( DeprecatedSettingWarning(old, "SENTRY_OPTIONS['%s']" % new)) settings.SENTRY_OPTIONS[new] = getattr(settings, old) if hasattr(settings, 'SENTRY_REDIS_OPTIONS'): if 'redis.clusters' in settings.SENTRY_OPTIONS: raise Exception("Cannot specify both SENTRY_OPTIONS['redis.clusters'] option and SENTRY_REDIS_OPTIONS setting.") else: warnings.warn( DeprecatedSettingWarning( 'SENTRY_REDIS_OPTIONS', 'SENTRY_OPTIONS["redis.clusters"]', removed_in_version='8.5', ) ) settings.SENTRY_OPTIONS['redis.clusters'] = { 'default': settings.SENTRY_REDIS_OPTIONS, } else: # Provide backwards compatibility to plugins expecting there to be a # ``SENTRY_REDIS_OPTIONS`` setting by using the ``default`` cluster. # This should be removed when ``SENTRY_REDIS_OPTIONS`` is officially # deprecated. (This also assumes ``FLAG_NOSTORE`` on the configuration # option.) settings.SENTRY_REDIS_OPTIONS = options.get('redis.clusters')['default'] if not hasattr(settings, 'SENTRY_URL_PREFIX'): url_prefix = options.get('system.url-prefix', silent=True) if not url_prefix: # HACK: We need to have some value here for backwards compatibility url_prefix = 'http://sentry.example.com' settings.SENTRY_URL_PREFIX = url_prefix if settings.TIME_ZONE != 'UTC': # non-UTC timezones are not supported show_big_error('TIME_ZONE should be set to UTC') # Set ALLOWED_HOSTS if it's not already available if not settings.ALLOWED_HOSTS: settings.ALLOWED_HOSTS = ['*'] if hasattr(settings, 'SENTRY_ALLOW_REGISTRATION'): warnings.warn(DeprecatedSettingWarning('SENTRY_ALLOW_REGISTRATION', 'SENTRY_FEATURES["auth:register"]')) settings.SENTRY_FEATURES['auth:register'] = settings.SENTRY_ALLOW_REGISTRATION settings.DEFAULT_FROM_EMAIL = settings.SENTRY_OPTIONS.get( 'mail.from', settings.SENTRY_DEFAULT_OPTIONS.get('mail.from')) # HACK(mattrobenolt): This is a one-off assertion for a system.secret-key value. # If this becomes a pattern, we could add another flag to the OptionsManager to cover this, but for now # this is the only value that should prevent the app from booting up. Currently FLAG_REQUIRED is used to # trigger the Installation Wizard, not abort startup. if not settings.SENTRY_OPTIONS.get('system.secret-key'): from .importer import ConfigurationError raise ConfigurationError("`system.secret-key` MUST be set. Use 'sentry config generate-secret-key' to get one.")
def initialize_app(config, skip_service_validation=False): settings = config["settings"] if settings.DEBUG: # Enable line buffering for stderr, TODO(py3.9) can be removed after py3.9, see bpo-13601 sys.stderr = os.fdopen(sys.stderr.fileno(), "w", 1) sys.stdout = os.fdopen(sys.stdout.fileno(), "w", 1) # Just reuse the integration app for Single Org / Self-Hosted as # it doesn't make much sense to use 2 separate apps for SSO and # integration. if settings.SENTRY_SINGLE_ORGANIZATION: options_mapper.update( { "github-app.client-id": "GITHUB_APP_ID", "github-app.client-secret": "GITHUB_API_SECRET", } ) bootstrap_options(settings, config["options"]) configure_structlog() # Commonly setups don't correctly configure themselves for production envs # so lets try to provide a bit more guidance if settings.CELERY_ALWAYS_EAGER and not settings.DEBUG: warnings.warn( "Sentry is configured to run asynchronous tasks in-process. " "This is not recommended within production environments. " "See https://docs.sentry.io/on-premise/server/queue/ for more information." ) if settings.SENTRY_SINGLE_ORGANIZATION: settings.SENTRY_FEATURES["organizations:create"] = False if not hasattr(settings, "SUDO_COOKIE_SECURE"): settings.SUDO_COOKIE_SECURE = getattr(settings, "SESSION_COOKIE_SECURE", False) if not hasattr(settings, "SUDO_COOKIE_DOMAIN"): settings.SUDO_COOKIE_DOMAIN = getattr(settings, "SESSION_COOKIE_DOMAIN", None) if not hasattr(settings, "SUDO_COOKIE_PATH"): settings.SUDO_COOKIE_PATH = getattr(settings, "SESSION_COOKIE_PATH", "/") if not hasattr(settings, "CSRF_COOKIE_SECURE"): settings.CSRF_COOKIE_SECURE = getattr(settings, "SESSION_COOKIE_SECURE", False) if not hasattr(settings, "CSRF_COOKIE_DOMAIN"): settings.CSRF_COOKIE_DOMAIN = getattr(settings, "SESSION_COOKIE_DOMAIN", None) if not hasattr(settings, "CSRF_COOKIE_PATH"): settings.CSRF_COOKIE_PATH = getattr(settings, "SESSION_COOKIE_PATH", "/") for key in settings.CACHES: if not hasattr(settings.CACHES[key], "VERSION"): settings.CACHES[key]["VERSION"] = 2 settings.ASSET_VERSION = get_asset_version(settings) settings.STATIC_URL = settings.STATIC_URL.format(version=settings.ASSET_VERSION) if getattr(settings, "SENTRY_DEBUGGER", None) is None: settings.SENTRY_DEBUGGER = settings.DEBUG monkeypatch_model_unpickle() import django django.setup() monkeypatch_django_migrations() apply_legacy_settings(settings) bind_cache_to_option_store() register_plugins(settings) initialize_receivers() validate_options(settings) validate_snuba() configure_sdk() setup_services(validate=not skip_service_validation) from django.utils import timezone from sentry.app import env from sentry.runner.settings import get_sentry_conf env.data["config"] = get_sentry_conf() env.data["start_date"] = timezone.now()
def apply_legacy_settings(settings): from sentry import options # SENTRY_USE_QUEUE used to determine if Celery was eager or not if hasattr(settings, 'SENTRY_USE_QUEUE'): warnings.warn( DeprecatedSettingWarning( 'SENTRY_USE_QUEUE', 'CELERY_ALWAYS_EAGER', 'https://docs.getsentry.com/on-premise/server/queue/', ) ) settings.CELERY_ALWAYS_EAGER = (not settings.SENTRY_USE_QUEUE) for old, new in ( ('SENTRY_ADMIN_EMAIL', 'system.admin-email'), ('SENTRY_URL_PREFIX', 'system.url-prefix'), ('SENTRY_SYSTEM_MAX_EVENTS_PER_MINUTE', 'system.rate-limit'), ): if new not in settings.SENTRY_OPTIONS and hasattr(settings, old): warnings.warn( DeprecatedSettingWarning(old, "SENTRY_OPTIONS['%s']" % new)) settings.SENTRY_OPTIONS[new] = getattr(settings, old) if hasattr(settings, 'SENTRY_REDIS_OPTIONS'): if 'redis.clusters' in settings.SENTRY_OPTIONS: raise Exception("Cannot specify both SENTRY_OPTIONS['redis.clusters'] option and SENTRY_REDIS_OPTIONS setting.") else: warnings.warn( DeprecatedSettingWarning( 'SENTRY_REDIS_OPTIONS', 'SENTRY_OPTIONS["redis.clusters"]', removed_in_version='8.5', ) ) settings.SENTRY_OPTIONS['redis.clusters'] = { 'default': settings.SENTRY_REDIS_OPTIONS, } else: # Provide backwards compatibility to plugins expecting there to be a # ``SENTRY_REDIS_OPTIONS`` setting by using the ``default`` cluster. # This should be removed when ``SENTRY_REDIS_OPTIONS`` is officially # deprecated. (This also assumes ``FLAG_NOSTORE`` on the configuration # option.) settings.SENTRY_REDIS_OPTIONS = options.get('redis.clusters')['default'] if not hasattr(settings, 'SENTRY_URL_PREFIX'): url_prefix = options.get('system.url-prefix', silent=True) if not url_prefix: # HACK: We need to have some value here for backwards compatibility url_prefix = 'http://sentry.example.com' settings.SENTRY_URL_PREFIX = url_prefix if settings.TIME_ZONE != 'UTC': # non-UTC timezones are not supported show_big_error('TIME_ZONE should be set to UTC') # Set ALLOWED_HOSTS if it's not already available if not settings.ALLOWED_HOSTS: settings.ALLOWED_HOSTS = ['*'] if hasattr(settings, 'SENTRY_ALLOW_REGISTRATION'): warnings.warn(DeprecatedSettingWarning('SENTRY_ALLOW_REGISTRATION', 'SENTRY_FEATURES["auth:register"]')) settings.SENTRY_FEATURES['auth:register'] = settings.SENTRY_ALLOW_REGISTRATION settings.DEFAULT_FROM_EMAIL = settings.SENTRY_OPTIONS.get( 'mail.from', settings.SENTRY_DEFAULT_OPTIONS.get('mail.from'))
def apply_legacy_settings(settings): # SENTRY_USE_QUEUE used to determine if Celery was eager or not if hasattr(settings, 'SENTRY_USE_QUEUE'): warnings.warn( DeprecatedSettingWarning( 'SENTRY_USE_QUEUE', 'CELERY_ALWAYS_EAGER', 'https://docs.getsentry.com/on-premise/server/queue/', )) settings.CELERY_ALWAYS_EAGER = (not settings.SENTRY_USE_QUEUE) if not settings.SENTRY_OPTIONS.get('system.admin-email') and hasattr( settings, 'SENTRY_ADMIN_EMAIL'): warnings.warn( DeprecatedSettingWarning('SENTRY_ADMIN_EMAIL', 'SENTRY_OPTIONS["system.admin-email"]')) settings.SENTRY_OPTIONS[ 'system.admin-email'] = settings.SENTRY_ADMIN_EMAIL if not settings.SENTRY_OPTIONS.get('system.url-prefix') and hasattr( settings, 'SENTRY_URL_PREFIX'): warnings.warn( DeprecatedSettingWarning('SENTRY_URL_PREFIX', 'SENTRY_OPTIONS["system.url-prefix"]')) settings.SENTRY_OPTIONS[ 'system.url-prefix'] = settings.SENTRY_URL_PREFIX if not settings.SENTRY_OPTIONS.get('system.rate-limit') and hasattr( settings, 'SENTRY_SYSTEM_MAX_EVENTS_PER_MINUTE'): warnings.warn( DeprecatedSettingWarning('SENTRY_SYSTEM_MAX_EVENTS_PER_MINUTE', 'SENTRY_OPTIONS["system.rate-limit"]')) settings.SENTRY_OPTIONS[ 'system.rate-limit'] = settings.SENTRY_SYSTEM_MAX_EVENTS_PER_MINUTE if hasattr(settings, 'SENTRY_REDIS_OPTIONS'): if 'redis.clusters' in settings.SENTRY_OPTIONS: raise Exception( "Cannot specify both SENTRY_OPTIONS['redis.clusters'] option and SENTRY_REDIS_OPTIONS setting." ) else: warnings.warn( DeprecatedSettingWarning( 'SENTRY_REDIS_OPTIONS', 'SENTRY_OPTIONS["redis.clusters"]', removed_in_version='8.5', )) settings.SENTRY_OPTIONS['redis.clusters'] = { 'default': settings.SENTRY_REDIS_OPTIONS, } else: # Provide backwards compatibility to plugins expecting there to be a # ``SENTRY_REDIS_OPTIONS`` setting by using the ``default`` cluster. # This should be removed when ``SENTRY_REDIS_OPTIONS`` is officially # deprecated. (This also assumes ``FLAG_NOSTORE`` on the configuration # option.) from sentry import options settings.SENTRY_REDIS_OPTIONS = options.get( 'redis.clusters')['default'] if not hasattr(settings, 'SENTRY_URL_PREFIX'): from sentry import options url_prefix = options.get('system.url-prefix', silent=True) if not url_prefix: # HACK: We need to have some value here for backwards compatibility url_prefix = 'http://sentry.example.com' settings.SENTRY_URL_PREFIX = url_prefix if settings.TIME_ZONE != 'UTC': # non-UTC timezones are not supported show_big_error('TIME_ZONE should be set to UTC') # Set ALLOWED_HOSTS if it's not already available if not settings.ALLOWED_HOSTS: from .hacks import AllowedHosts settings.ALLOWED_HOSTS = AllowedHosts() if hasattr(settings, 'SENTRY_ALLOW_REGISTRATION'): warnings.warn( DeprecatedSettingWarning('SENTRY_ALLOW_REGISTRATION', 'SENTRY_FEATURES["auth:register"]')) settings.SENTRY_FEATURES[ 'auth:register'] = settings.SENTRY_ALLOW_REGISTRATION
def initialize_app(config, skip_service_validation=False): settings = config['settings'] bootstrap_options(settings, config['options']) from clims.logs import configure_logging configure_logging() if 'south' in settings.INSTALLED_APPS: fix_south(settings) # Commonly setups don't correctly configure themselves for production envs # so lets try to provide a bit more guidance if settings.CELERY_ALWAYS_EAGER and not settings.DEBUG: warnings.warn( 'Sentry is configured to run asynchronous tasks in-process. ' 'This is not recommended within production environments. ' 'See https://docs.sentry.io/on-premise/server/queue/ for more information.' ) if settings.SENTRY_SINGLE_ORGANIZATION: settings.SENTRY_FEATURES['organizations:create'] = False if not hasattr(settings, 'SUDO_COOKIE_SECURE'): settings.SUDO_COOKIE_SECURE = getattr(settings, 'SESSION_COOKIE_SECURE', False) if not hasattr(settings, 'SUDO_COOKIE_DOMAIN'): settings.SUDO_COOKIE_DOMAIN = getattr(settings, 'SESSION_COOKIE_DOMAIN', None) if not hasattr(settings, 'SUDO_COOKIE_PATH'): settings.SUDO_COOKIE_PATH = getattr(settings, 'SESSION_COOKIE_PATH', '/') if not hasattr(settings, 'CSRF_COOKIE_SECURE'): settings.CSRF_COOKIE_SECURE = getattr(settings, 'SESSION_COOKIE_SECURE', False) if not hasattr(settings, 'CSRF_COOKIE_DOMAIN'): settings.CSRF_COOKIE_DOMAIN = getattr(settings, 'SESSION_COOKIE_DOMAIN', None) if not hasattr(settings, 'CSRF_COOKIE_PATH'): settings.CSRF_COOKIE_PATH = getattr(settings, 'SESSION_COOKIE_PATH', '/') settings.CACHES['default']['VERSION'] = settings.CACHE_VERSION settings.ASSET_VERSION = get_asset_version(settings) settings.STATIC_URL = settings.STATIC_URL.format( version=settings.ASSET_VERSION, ) import django django.setup() bind_cache_to_option_store() from clims.services.application import ioc, ApplicationService app = ApplicationService() ioc.set_application(app) app.plugins.load_installed() initialize_receivers() validate_options(settings) setup_services(validate=not skip_service_validation) from django.utils import timezone from sentry.app import env from sentry.runner.settings import get_sentry_conf env.data['config'] = get_sentry_conf() env.data['start_date'] = timezone.now()
def apply_legacy_settings(settings): from sentry import options # SENTRY_USE_QUEUE used to determine if Celery was eager or not if hasattr(settings, "SENTRY_USE_QUEUE"): warnings.warn( DeprecatedSettingWarning( "SENTRY_USE_QUEUE", "CELERY_ALWAYS_EAGER", "https://docs.getsentry.com/on-premise/server/queue/" ) ) settings.CELERY_ALWAYS_EAGER = not settings.SENTRY_USE_QUEUE for old, new in ( ("SENTRY_ADMIN_EMAIL", "system.admin-email"), ("SENTRY_URL_PREFIX", "system.url-prefix"), ("SENTRY_SYSTEM_MAX_EVENTS_PER_MINUTE", "system.rate-limit"), ("SENTRY_ENABLE_EMAIL_REPLIES", "mail.enable-replies"), ("SENTRY_SMTP_HOSTNAME", "mail.reply-hostname"), ("MAILGUN_API_KEY", "mail.mailgun-api-key"), ): if new not in settings.SENTRY_OPTIONS and hasattr(settings, old): warnings.warn(DeprecatedSettingWarning(old, "SENTRY_OPTIONS['%s']" % new)) settings.SENTRY_OPTIONS[new] = getattr(settings, old) if hasattr(settings, "SENTRY_REDIS_OPTIONS"): if "redis.clusters" in settings.SENTRY_OPTIONS: raise Exception( "Cannot specify both SENTRY_OPTIONS['redis.clusters'] option and SENTRY_REDIS_OPTIONS setting." ) else: warnings.warn( DeprecatedSettingWarning( "SENTRY_REDIS_OPTIONS", 'SENTRY_OPTIONS["redis.clusters"]', removed_in_version="8.5" ) ) settings.SENTRY_OPTIONS["redis.clusters"] = {"default": settings.SENTRY_REDIS_OPTIONS} else: # Provide backwards compatibility to plugins expecting there to be a # ``SENTRY_REDIS_OPTIONS`` setting by using the ``default`` cluster. # This should be removed when ``SENTRY_REDIS_OPTIONS`` is officially # deprecated. (This also assumes ``FLAG_NOSTORE`` on the configuration # option.) settings.SENTRY_REDIS_OPTIONS = options.get("redis.clusters")["default"] if not hasattr(settings, "SENTRY_URL_PREFIX"): url_prefix = options.get("system.url-prefix", silent=True) if not url_prefix: # HACK: We need to have some value here for backwards compatibility url_prefix = "http://sentry.example.com" settings.SENTRY_URL_PREFIX = url_prefix if settings.TIME_ZONE != "UTC": # non-UTC timezones are not supported show_big_error("TIME_ZONE should be set to UTC") # Set ALLOWED_HOSTS if it's not already available if not settings.ALLOWED_HOSTS: settings.ALLOWED_HOSTS = ["*"] if hasattr(settings, "SENTRY_ALLOW_REGISTRATION"): warnings.warn(DeprecatedSettingWarning("SENTRY_ALLOW_REGISTRATION", 'SENTRY_FEATURES["auth:register"]')) settings.SENTRY_FEATURES["auth:register"] = settings.SENTRY_ALLOW_REGISTRATION settings.DEFAULT_FROM_EMAIL = settings.SENTRY_OPTIONS.get( "mail.from", settings.SENTRY_DEFAULT_OPTIONS.get("mail.from") )