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:
josephschorr 2018-02-06 16:39:24 -05:00 committed by GitHub
commit 61363f0ffc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 266 additions and 10 deletions

View file

@ -196,9 +196,6 @@ class DefaultConfig(ImmutableConfig):
# Feature Flag: Whether Google login is supported. # Feature Flag: Whether Google login is supported.
FEATURE_GOOGLE_LOGIN = False FEATURE_GOOGLE_LOGIN = False
# Feature Flag: Whether Dex login is supported.
FEATURE_DEX_LOGIN = False
# Feature Flag: whether to enable support chat # Feature Flag: whether to enable support chat
FEATURE_SUPPORT_CHAT = False FEATURE_SUPPORT_CHAT = False

View file

@ -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 = { CONFIG_SCHEMA = {
'type': 'object', 'type': 'object',
'description': 'Schema for Quay configuration', 'description': 'Schema for Quay configuration',
@ -99,17 +185,17 @@ CONFIG_SCHEMA = {
'x-example': 588, 'x-example': 588,
}, },
'MAIL_USERNAME': { 'MAIL_USERNAME': {
'type': 'string', 'type': ['string', 'null'],
'description': 'The SMTP username to use when sending e-mails.', 'description': 'The SMTP username to use when sending e-mails.',
'x-example': 'myuser', 'x-example': 'myuser',
}, },
'MAIL_PASSWORD': { 'MAIL_PASSWORD': {
'type': 'string', 'type': ['string', 'null'],
'description': 'The SMTP password to use when sending e-mails.', 'description': 'The SMTP password to use when sending e-mails.',
'x-example': 'mypassword', 'x-example': 'mypassword',
}, },
'MAIL_DEFAULT_SENDER': { '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`.', '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', 'x-example': 'support@myco.com',
}, },
@ -121,6 +207,33 @@ CONFIG_SCHEMA = {
'x-example': 'mysql+pymysql://username:password@dns.of.database/quay', 'x-example': 'mysql+pymysql://username:password@dns.of.database/quay',
'x-reference': 'https://www.postgresql.org/docs/9.3/static/libpq-connect.html#AEN39495', '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': { 'ALLOW_PULLS_WITHOUT_STRICT_LOGGING': {
'type': 'boolean', 'type': 'boolean',
'description': 'If true, pulls in which the pull audit log entry cannot be written will ' + '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'], '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.
'AUTHENTICATION_TYPE': { 'AUTHENTICATION_TYPE': {
@ -254,7 +401,7 @@ CONFIG_SCHEMA = {
# OAuth configuration. # OAuth configuration.
'GITHUB_LOGIN_CONFIG': { 'GITHUB_LOGIN_CONFIG': {
'type': 'object', 'type': ['object', 'null'],
'description': 'Configuration for using GitHub (Enterprise) as an external login provider', 'description': 'Configuration for using GitHub (Enterprise) as an external login provider',
'required': ['GITHUB_ENDPOINT', 'CLIENT_ID', 'CLIENT_SECRET'], 'required': ['GITHUB_ENDPOINT', 'CLIENT_ID', 'CLIENT_SECRET'],
'x-reference': 'https://coreos.com/quay-enterprise/docs/latest/github-auth.html', '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': { 'GITHUB_TRIGGER_CONFIG': {
'type': 'object', 'type': ['object', 'null'],
'description': 'Configuration for using GitHub (Enterprise) for build triggers', 'description': 'Configuration for using GitHub (Enterprise) for build triggers',
'required': ['GITHUB_ENDPOINT', 'CLIENT_ID', 'CLIENT_SECRET'], 'required': ['GITHUB_ENDPOINT', 'CLIENT_ID', 'CLIENT_SECRET'],
'x-reference': 'https://coreos.com/quay-enterprise/docs/latest/github-build.html', 'x-reference': 'https://coreos.com/quay-enterprise/docs/latest/github-build.html',
@ -327,7 +492,7 @@ CONFIG_SCHEMA = {
}, },
}, },
'GOOGLE_LOGIN_CONFIG': { 'GOOGLE_LOGIN_CONFIG': {
'type': 'object', 'type': ['object', 'null'],
'description': 'Configuration for using Google for external authentication', 'description': 'Configuration for using Google for external authentication',
'required': ['CLIENT_ID', 'CLIENT_SECRET'], 'required': ['CLIENT_ID', 'CLIENT_SECRET'],
'properties': { 'properties': {
@ -344,7 +509,7 @@ CONFIG_SCHEMA = {
}, },
}, },
'GITLAB_TRIGGER_CONFIG': { 'GITLAB_TRIGGER_CONFIG': {
'type': 'object', 'type': ['object', 'null'],
'description': 'Configuration for using Gitlab (Enterprise) for external authentication', 'description': 'Configuration for using Gitlab (Enterprise) for external authentication',
'required': ['GITLAB_ENDPOINT', 'CLIENT_ID', 'CLIENT_SECRET'], 'required': ['GITLAB_ENDPOINT', 'CLIENT_ID', 'CLIENT_SECRET'],
'properties': { '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. # 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': { 'PUBLIC_NAMESPACES': {
'type': 'array', 'type': 'array',
'description': 'If a namespace is defined in the public namespace list, then it will appear on *all*' + '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': { 'V2_PAGINATION_SIZE': {
'type': 'number', 'type': 'number',
'description': 'The number of results returned per page in V2 registry APIs', '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. # Time machine and tag expiration settings.
@ -420,6 +624,11 @@ CONFIG_SCHEMA = {
'x-example': '2h', 'x-example': '2h',
'pattern': '^[0-9]+(w|m|d|h|s)$', '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. # Security scanning.
'FEATURE_SECURITY_SCANNER': { 'FEATURE_SECURITY_SCANNER': {
@ -498,6 +707,35 @@ CONFIG_SCHEMA = {
'x-example': False, '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 Flag: Permanent Sessions.
'FEATURE_PERMANENT_SESSIONS': { 'FEATURE_PERMANENT_SESSIONS': {
'type': 'boolean', 'type': 'boolean',
@ -616,6 +854,20 @@ CONFIG_SCHEMA = {
'description': 'If set to true, autocompletion will apply to partial usernames. Defaults to True', 'description': 'If set to true, autocompletion will apply to partial usernames. Defaults to True',
'x-example': 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,
},
}, },
} }

View 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