Merge pull request #2997 from coreos-inc/joseph.schorr/QUAY-818/verify-schema
Add test to verify that all defined config fields are found in the schema
This commit is contained in:
commit
61363f0ffc
3 changed files with 266 additions and 10 deletions
|
@ -196,9 +196,6 @@ class DefaultConfig(ImmutableConfig):
|
|||
# Feature Flag: Whether Google login is supported.
|
||||
FEATURE_GOOGLE_LOGIN = False
|
||||
|
||||
# Feature Flag: Whether Dex login is supported.
|
||||
FEATURE_DEX_LOGIN = False
|
||||
|
||||
# Feature Flag: whether to enable support chat
|
||||
FEATURE_SUPPORT_CHAT = False
|
||||
|
||||
|
|
|
@ -1,3 +1,89 @@
|
|||
# INTERNAL_ONLY_PROPERTIES defines the properties in the config that, while settable, should
|
||||
# not be documented for external users. These will generally be used for internal test or only
|
||||
# given to customers when they have been briefed on the side effects of using them.
|
||||
INTERNAL_ONLY_PROPERTIES = {
|
||||
'__module__',
|
||||
'__doc__',
|
||||
'create_transaction',
|
||||
|
||||
'TESTING',
|
||||
'SEND_FILE_MAX_AGE_DEFAULT',
|
||||
|
||||
'REPLICATION_QUEUE_NAME',
|
||||
'DOCKERFILE_BUILD_QUEUE_NAME',
|
||||
'CHUNK_CLEANUP_QUEUE_NAME',
|
||||
'SECSCAN_NOTIFICATION_QUEUE_NAME',
|
||||
'SECURITY_SCANNER_ISSUER_NAME',
|
||||
'NOTIFICATION_QUEUE_NAME',
|
||||
|
||||
'FEATURE_BILLING',
|
||||
'FEATURE_SUPPORT_CHAT',
|
||||
'BILLING_TYPE',
|
||||
|
||||
'INSTANCE_SERVICE_KEY_LOCATION',
|
||||
'INSTANCE_SERVICE_KEY_REFRESH',
|
||||
'INSTANCE_SERVICE_KEY_SERVICE',
|
||||
'INSTANCE_SERVICE_KEY_KID_LOCATION',
|
||||
'INSTANCE_SERVICE_KEY_EXPIRATION',
|
||||
'UNAPPROVED_SERVICE_KEY_TTL_SEC',
|
||||
'EXPIRED_SERVICE_KEY_TTL_SEC',
|
||||
'REGISTRY_JWT_AUTH_MAX_FRESH_S',
|
||||
|
||||
'BITTORRENT_FILENAME_PEPPER',
|
||||
'BITTORRENT_WEBSEED_LIFETIME',
|
||||
|
||||
'SERVICE_LOG_ACCOUNT_ID',
|
||||
'BUILDLOGS_OPTIONS',
|
||||
'LIBRARY_NAMESPACE',
|
||||
'STAGGER_WORKERS',
|
||||
'QUEUE_WORKER_METRICS_REFRESH_SECONDS',
|
||||
'PUSH_TEMP_TAG_EXPIRATION_SEC',
|
||||
'GARBAGE_COLLECTION_FREQUENCY',
|
||||
'PAGE_TOKEN_KEY',
|
||||
'BUILD_MANAGER',
|
||||
'JWTPROXY_AUDIENCE',
|
||||
'SYSTEM_SERVICE_BLACKLIST',
|
||||
'JWTPROXY_SIGNER',
|
||||
'SECURITY_SCANNER_INDEXING_MIN_ID',
|
||||
'MAX_BUILD_QUEUE_RATE_SECS',
|
||||
'STATIC_SITE_BUCKET',
|
||||
'LABEL_KEY_RESERVED_PREFIXES',
|
||||
'TEAM_SYNC_WORKER_FREQUENCY',
|
||||
'DOCUMENTATION_METADATA',
|
||||
'DOCUMENTATION_LOCATION',
|
||||
'JSONIFY_PRETTYPRINT_REGULAR',
|
||||
'SYSTEM_LOGS_FILE',
|
||||
'SYSTEM_LOGS_PATH',
|
||||
'SYSTEM_SERVICES_PATH',
|
||||
'TUF_GUN_PREFIX',
|
||||
'LOGGING_LEVEL',
|
||||
'SIGNED_GRANT_EXPIRATION_SEC',
|
||||
'PROMETHEUS_AGGREGATOR_URL',
|
||||
'DB_TRANSACTION_FACTORY',
|
||||
'NOTIFICATION_SEND_TIMEOUT',
|
||||
'QUEUE_METRICS_TYPE',
|
||||
'MAIL_FAIL_SILENTLY',
|
||||
'LOCAL_OAUTH_HANDLER',
|
||||
'USE_CDN',
|
||||
'MAX_BUILD_QUEUE_RATE_ITEMS',
|
||||
'ANALYTICS_TYPE',
|
||||
|
||||
'EXCEPTION_LOG_TYPE',
|
||||
'SENTRY_DSN',
|
||||
'SENTRY_PUBLIC_DSN',
|
||||
|
||||
'SECURITY_SCANNER_ENDPOINT_BATCH',
|
||||
'SECURITY_SCANNER_API_TIMEOUT_SECONDS',
|
||||
'SECURITY_SCANNER_API_TIMEOUT_POST_SECONDS',
|
||||
'SECURITY_SCANNER_ENGINE_VERSION_TARGET',
|
||||
'SECURITY_SCANNER_READONLY_FAILOVER_ENDPOINTS',
|
||||
'SECURITY_SCANNER_API_VERSION',
|
||||
|
||||
# TODO: move this into the schema once we support signing in QE.
|
||||
'FEATURE_SIGNING',
|
||||
'TUF_SERVER',
|
||||
}
|
||||
|
||||
CONFIG_SCHEMA = {
|
||||
'type': 'object',
|
||||
'description': 'Schema for Quay configuration',
|
||||
|
@ -99,17 +185,17 @@ CONFIG_SCHEMA = {
|
|||
'x-example': 588,
|
||||
},
|
||||
'MAIL_USERNAME': {
|
||||
'type': 'string',
|
||||
'type': ['string', 'null'],
|
||||
'description': 'The SMTP username to use when sending e-mails.',
|
||||
'x-example': 'myuser',
|
||||
},
|
||||
'MAIL_PASSWORD': {
|
||||
'type': 'string',
|
||||
'type': ['string', 'null'],
|
||||
'description': 'The SMTP password to use when sending e-mails.',
|
||||
'x-example': 'mypassword',
|
||||
},
|
||||
'MAIL_DEFAULT_SENDER': {
|
||||
'type': 'string',
|
||||
'type': ['string', 'null'],
|
||||
'description': 'If specified, the e-mail address used as the `from` when Quay sends e-mails. If none, defaults to `support@quay.io`.',
|
||||
'x-example': 'support@myco.com',
|
||||
},
|
||||
|
@ -121,6 +207,33 @@ CONFIG_SCHEMA = {
|
|||
'x-example': 'mysql+pymysql://username:password@dns.of.database/quay',
|
||||
'x-reference': 'https://www.postgresql.org/docs/9.3/static/libpq-connect.html#AEN39495',
|
||||
},
|
||||
'DB_CONNECTION_ARGS': {
|
||||
'type': 'object',
|
||||
'description': 'If specified, connection arguments for the database such as timeouts and SSL.',
|
||||
'properties': {
|
||||
'threadlocals': {
|
||||
'type': 'boolean',
|
||||
'description': 'Whether to use thread-local connections. Should *ALWAYS* be `true`'
|
||||
},
|
||||
'autorollback': {
|
||||
'type': 'boolean',
|
||||
'description': 'Whether to use auto-rollback connections. Should *ALWAYS* be `true`'
|
||||
},
|
||||
'ssl': {
|
||||
'type': 'object',
|
||||
'description': 'SSL connection configuration',
|
||||
'properties': {
|
||||
'ca': {
|
||||
'type': 'string',
|
||||
'description': '*Absolute container path* to the CA certificate to use for SSL connections',
|
||||
'x-example': 'conf/stack/ssl-ca-cert.pem',
|
||||
},
|
||||
},
|
||||
'required': ['ca'],
|
||||
},
|
||||
},
|
||||
'required': ['threadlocals', 'autorollback'],
|
||||
},
|
||||
'ALLOW_PULLS_WITHOUT_STRICT_LOGGING': {
|
||||
'type': 'boolean',
|
||||
'description': 'If true, pulls in which the pull audit log entry cannot be written will ' +
|
||||
|
@ -179,6 +292,40 @@ CONFIG_SCHEMA = {
|
|||
},
|
||||
'x-example': ['s3_us_east', 's3_us_west'],
|
||||
},
|
||||
'USERFILES_LOCATION': {
|
||||
'type': 'string',
|
||||
'description': 'ID of the storage engine in which to place user-uploaded files',
|
||||
'x-example': 's3_us_east',
|
||||
},
|
||||
'USERFILES_PATH': {
|
||||
'type': 'string',
|
||||
'description': 'Path under storage in which to place user-uploaded files',
|
||||
'x-example': 'userfiles',
|
||||
},
|
||||
'ACTION_LOG_ARCHIVE_LOCATION': {
|
||||
'type': 'string',
|
||||
'description': 'If action log archiving is enabled, the storage engine in which to place the ' +
|
||||
'archived data.',
|
||||
'x-example': 's3_us_east',
|
||||
},
|
||||
'ACTION_LOG_ARCHIVE_PATH': {
|
||||
'type': 'string',
|
||||
'description': 'If action log archiving is enabled, the path in storage in which to place the ' +
|
||||
'archived data.',
|
||||
'x-example': 'archives/actionlogs',
|
||||
},
|
||||
'LOG_ARCHIVE_LOCATION': {
|
||||
'type': 'string',
|
||||
'description': 'If builds are enabled, the storage engine in which to place the ' +
|
||||
'archived build logs.',
|
||||
'x-example': 's3_us_east',
|
||||
},
|
||||
'LOG_ARCHIVE_PATH': {
|
||||
'type': 'string',
|
||||
'description': 'If builds are enabled, the path in storage in which to place the ' +
|
||||
'archived build logs.',
|
||||
'x-example': 'archives/buildlogs',
|
||||
},
|
||||
|
||||
# Authentication.
|
||||
'AUTHENTICATION_TYPE': {
|
||||
|
@ -254,7 +401,7 @@ CONFIG_SCHEMA = {
|
|||
|
||||
# OAuth configuration.
|
||||
'GITHUB_LOGIN_CONFIG': {
|
||||
'type': 'object',
|
||||
'type': ['object', 'null'],
|
||||
'description': 'Configuration for using GitHub (Enterprise) as an external login provider',
|
||||
'required': ['GITHUB_ENDPOINT', 'CLIENT_ID', 'CLIENT_SECRET'],
|
||||
'x-reference': 'https://coreos.com/quay-enterprise/docs/latest/github-auth.html',
|
||||
|
@ -296,8 +443,26 @@ CONFIG_SCHEMA = {
|
|||
},
|
||||
},
|
||||
},
|
||||
'BITBUCKET_TRIGGER_CONFIG': {
|
||||
'type': ['object', 'null'],
|
||||
'description': 'Configuration for using BitBucket for build triggers',
|
||||
'required': ['CLIENT_ID', 'CLIENT_SECRET'],
|
||||
'x-reference': 'https://coreos.com/quay-enterprise/docs/latest/bitbucket-build.html',
|
||||
'properties': {
|
||||
'CLIENT_ID': {
|
||||
'type': 'string',
|
||||
'description': 'The registered client ID for this Quay instance',
|
||||
'x-example': '0e8dbe15c4c7630b6780',
|
||||
},
|
||||
'CLIENT_SECRET': {
|
||||
'type': 'string',
|
||||
'description': 'The registered client secret for this Quay instance',
|
||||
'x-example': 'e4a58ddd3d7408b7aec109e85564a0d153d3e846',
|
||||
},
|
||||
},
|
||||
},
|
||||
'GITHUB_TRIGGER_CONFIG': {
|
||||
'type': 'object',
|
||||
'type': ['object', 'null'],
|
||||
'description': 'Configuration for using GitHub (Enterprise) for build triggers',
|
||||
'required': ['GITHUB_ENDPOINT', 'CLIENT_ID', 'CLIENT_SECRET'],
|
||||
'x-reference': 'https://coreos.com/quay-enterprise/docs/latest/github-build.html',
|
||||
|
@ -327,7 +492,7 @@ CONFIG_SCHEMA = {
|
|||
},
|
||||
},
|
||||
'GOOGLE_LOGIN_CONFIG': {
|
||||
'type': 'object',
|
||||
'type': ['object', 'null'],
|
||||
'description': 'Configuration for using Google for external authentication',
|
||||
'required': ['CLIENT_ID', 'CLIENT_SECRET'],
|
||||
'properties': {
|
||||
|
@ -344,7 +509,7 @@ CONFIG_SCHEMA = {
|
|||
},
|
||||
},
|
||||
'GITLAB_TRIGGER_CONFIG': {
|
||||
'type': 'object',
|
||||
'type': ['object', 'null'],
|
||||
'description': 'Configuration for using Gitlab (Enterprise) for external authentication',
|
||||
'required': ['GITLAB_ENDPOINT', 'CLIENT_ID', 'CLIENT_SECRET'],
|
||||
'properties': {
|
||||
|
@ -366,7 +531,39 @@ CONFIG_SCHEMA = {
|
|||
},
|
||||
},
|
||||
|
||||
# Health.
|
||||
'HEALTH_CHECKER': {
|
||||
'description': 'The configured health check.',
|
||||
'x-example': ('RDSAwareHealthCheck', {'access_key': 'foo', 'secret_key': 'bar'}),
|
||||
},
|
||||
|
||||
# Metrics.
|
||||
'PROMETHEUS_NAMESPACE': {
|
||||
'type': 'string',
|
||||
'description': 'The prefix applied to all exposed Prometheus metrics. Defaults to `quay`',
|
||||
'x-example': 'myregistry',
|
||||
},
|
||||
|
||||
# Misc configuration.
|
||||
'BLACKLIST_V2_SPEC': {
|
||||
'type': 'string',
|
||||
'description': 'The Docker CLI versions to which Quay will respond that V2 is *unsupported*. Defaults to `<1.6.0`',
|
||||
'x-reference': 'http://pythonhosted.org/semantic_version/reference.html#semantic_version.Spec',
|
||||
'x-example': '<1.8.0',
|
||||
},
|
||||
'USER_RECOVERY_TOKEN_LIFETIME': {
|
||||
'type': 'string',
|
||||
'description': 'The length of time a token for recovering a user accounts is valid. Defaults to 30m.',
|
||||
'x-example': '10m',
|
||||
'pattern': '^[0-9]+(w|m|d|h|s)$',
|
||||
},
|
||||
'SESSION_COOKIE_SECURE': {
|
||||
'type': 'boolean',
|
||||
'description': 'Whether the `secure` property should be set on session cookies. ' +
|
||||
'Defaults to False. Recommended to be True for all installations using SSL.',
|
||||
'x-example': True,
|
||||
'x-reference': 'https://en.wikipedia.org/wiki/Secure_cookies',
|
||||
},
|
||||
'PUBLIC_NAMESPACES': {
|
||||
'type': 'array',
|
||||
'description': 'If a namespace is defined in the public namespace list, then it will appear on *all*' +
|
||||
|
@ -386,6 +583,13 @@ CONFIG_SCHEMA = {
|
|||
'V2_PAGINATION_SIZE': {
|
||||
'type': 'number',
|
||||
'description': 'The number of results returned per page in V2 registry APIs',
|
||||
'x-example': 100,
|
||||
},
|
||||
'ENABLE_HEALTH_DEBUG_SECRET': {
|
||||
'type': ['string', 'null'],
|
||||
'description': 'If specified, a secret that can be given to health endpoints to see full debug info when' +
|
||||
'not authenticated as a superuser',
|
||||
'x-example': 'somesecrethere',
|
||||
},
|
||||
|
||||
# Time machine and tag expiration settings.
|
||||
|
@ -420,6 +624,11 @@ CONFIG_SCHEMA = {
|
|||
'x-example': '2h',
|
||||
'pattern': '^[0-9]+(w|m|d|h|s)$',
|
||||
},
|
||||
'FEATURE_NONSUPERUSER_TEAM_SYNCING_SETUP': {
|
||||
'type': 'boolean',
|
||||
'description': 'If enabled, non-superusers can setup syncing on teams to backing LDAP or Keystone. Defaults To False.',
|
||||
'x-example': True,
|
||||
},
|
||||
|
||||
# Security scanning.
|
||||
'FEATURE_SECURITY_SCANNER': {
|
||||
|
@ -498,6 +707,35 @@ CONFIG_SCHEMA = {
|
|||
'x-example': False,
|
||||
},
|
||||
|
||||
# Recaptcha
|
||||
'FEATURE_RECAPTCHA': {
|
||||
'type': 'boolean',
|
||||
'description': 'Whether Recaptcha is necessary for user login and recovery. Defaults to False',
|
||||
'x-example': False,
|
||||
'x-reference': 'https://www.google.com/recaptcha/intro/',
|
||||
},
|
||||
'RECAPTCHA_SITE_KEY': {
|
||||
'type': 'string',
|
||||
'description': 'If recaptcha is enabled, the site key for the Recaptcha service',
|
||||
},
|
||||
'RECAPTCHA_SECRET_KEY': {
|
||||
'type': 'string',
|
||||
'description': 'If recaptcha is enabled, the secret key for the Recaptcha service',
|
||||
},
|
||||
|
||||
# External application tokens.
|
||||
'FEATURE_APP_SPECIFIC_TOKENS': {
|
||||
'type': 'boolean',
|
||||
'description': 'If enabled, users can create tokens for use by the Docker CLI. Defaults to True',
|
||||
'x-example': False,
|
||||
},
|
||||
|
||||
'APP_SPECIFIC_TOKEN_EXPIRATION': {
|
||||
'type': ['string', 'null'],
|
||||
'description': 'The expiration for external app tokens. Defaults to None.',
|
||||
'pattern': '^[0-9]+(w|m|d|h|s)$',
|
||||
},
|
||||
|
||||
# Feature Flag: Permanent Sessions.
|
||||
'FEATURE_PERMANENT_SESSIONS': {
|
||||
'type': 'boolean',
|
||||
|
@ -616,6 +854,20 @@ CONFIG_SCHEMA = {
|
|||
'description': 'If set to true, autocompletion will apply to partial usernames. Defaults to True',
|
||||
'x-example': True,
|
||||
},
|
||||
|
||||
# Feature Flag: User log access.
|
||||
'FEATURE_USER_LOG_ACCESS': {
|
||||
'type': 'boolean',
|
||||
'description': 'If set to true, users will have access to audit logs for their namespace. Defaults to False',
|
||||
'x-example': True,
|
||||
},
|
||||
|
||||
# Feature Flag: User renaming.
|
||||
'FEATURE_USER_RENAME': {
|
||||
'type': 'boolean',
|
||||
'description': 'If set to true, users can rename their own namespace. Defaults to False',
|
||||
'x-example': True,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
|
7
util/config/test/test_schema.py
Normal file
7
util/config/test/test_schema.py
Normal file
|
@ -0,0 +1,7 @@
|
|||
from config import DefaultConfig
|
||||
from util.config.schema import CONFIG_SCHEMA, INTERNAL_ONLY_PROPERTIES
|
||||
|
||||
def test_ensure_schema_defines_all_fields():
|
||||
for key in vars(DefaultConfig):
|
||||
has_key = key in CONFIG_SCHEMA['properties'] or key in INTERNAL_ONLY_PROPERTIES
|
||||
assert has_key, "Property `%s` is missing from config schema" % key
|
Reference in a new issue