1
0
mirror of https://github.com/quay/quay.git synced 2026-01-26 06:21:37 +03:00
Files
quay/data/model/__init__.py
Ivan Bazulic 62e42f8f54 storage: Disable pushes on registry (PROJQUAY-6870) (#2755)
* storage: Disable pushes on registry (PROJQUAY-6870)

The current read-only option for Quay is not sometimes feasible, since it requires an insert of the service key and other manual config changes. For instance, if you want to just recalculate quota on the registry, but would like to allow all registry operations (including UI) without the possibility of pushes until recalculation is done, setting the whole registry `read-only` cannot be done since it makes the database read only as well.

This PR introduces a new flag called `DISABLE_PUSHES` which allows all registry operations to continue (changing tags, repo editing, robot account creation/deletion, user creation etc.) but will disable pushes of new images to the registry (i.e. backend storage will not change). If a registry already contains the image and a new tag is simply being added, that operation should succeed.

The following message would appear in the logs:

~~~
gunicorn-registry stdout | 2024-03-13 20:19:49,414 [369] [DEBUG] [endpoints.v2] sending response: b'{"errors":[{"code":"METHOD NOT ALLOWED","detail":{},"message":"Pushes to the registry are currently disabled. Please contact the administrator for more information."}]}\n'
gunicorn-registry stdout | 2024-03-13 20:19:49,414 [369] [INFO] [gunicorn.access] 172.17.0.1 - - [13/Mar/2024:20:19:49 +0000] "PUT /v2/ibazulic/mariadb/manifests/sha256:c4694ba424e0259694a5117bbb510d67340051f0bdb7f9fa8033941a2d66e53e HTTP/1.1" 405 169 "-" "skopeo/1.9.3"
nginx stdout | 172.17.0.1 (-) - - [13/Mar/2024:20:19:49 +0000] "PUT /v2/ibazulic/mariadb/manifests/sha256:c4694ba424e0259694a5117bbb510d67340051f0bdb7f9fa8033941a2d66e53e HTTP/1.1" 405 169 "-" "skopeo/1.9.3" (0.002 3813 0.002)
~~~

The flag defaults to `False` (pushes enabled), unless set otherwise.

* Removed constraint on storage replication when pushes are disabled

* Rebase

* Fix isort sorting

* Fix isort sorting #2

* Removed constraint on storage replication when pushes are disabled

* Rebase

* Remove constraint on storage replication worker

* Fix linting on config.py
2024-08-07 15:40:10 -04:00

255 lines
4.4 KiB
Python

from data.database import db, db_transaction
class DataModelException(Exception):
pass
class InvalidLabelKeyException(DataModelException):
pass
class InvalidMediaTypeException(DataModelException):
pass
class BlobDoesNotExist(DataModelException):
pass
class InvalidBlobUpload(DataModelException):
pass
class InvalidEmailAddressException(DataModelException):
pass
class InvalidOrganizationException(DataModelException):
pass
class InvalidProxyCacheConfigException(DataModelException):
pass
class InvalidPasswordException(DataModelException):
pass
class InvalidRobotException(DataModelException):
pass
class DeactivatedRobotOwnerException(InvalidRobotException):
pass
class InvalidRobotCredentialException(InvalidRobotException):
pass
class InvalidRobotOwnerException(InvalidRobotException):
pass
class InvalidUsernameException(DataModelException):
pass
class RepositoryDoesNotExist(DataModelException):
pass
class InvalidRepositoryBuildException(DataModelException):
pass
class InvalidBuildTriggerException(DataModelException):
pass
class InvalidTokenException(DataModelException):
pass
class InvalidNotificationException(DataModelException):
pass
class InvalidImageException(DataModelException):
pass
class UserAlreadyInTeam(DataModelException):
pass
class InvalidTeamException(DataModelException):
pass
class InvalidTeamMemberException(DataModelException):
pass
class InvalidManifestException(DataModelException):
pass
class ManifestDoesNotExist(DataModelException):
pass
class ServiceKeyDoesNotExist(DataModelException):
pass
class ServiceKeyAlreadyApproved(DataModelException):
pass
class ServiceNameInvalid(DataModelException):
pass
class TagDoesNotExist(DataModelException):
pass
class TagAlreadyCreatedException(DataModelException):
pass
class StaleTagException(DataModelException):
pass
class InvalidSystemQuotaConfig(Exception):
pass
class QuotaExceededException(DataModelException):
pass
class InvalidNamespaceQuota(DataModelException):
pass
class InvalidNamespaceQuotaLimit(DataModelException):
pass
class InvalidNamespaceQuotaType(DataModelException):
pass
class UnsupportedQuotaSize(DataModelException):
pass
class OrgSubscriptionBindingAlreadyExists(DataModelException):
pass
class NamespaceAutoPrunePolicyAlreadyExists(DataModelException):
pass
class NamespaceAutoPrunePolicyDoesNotExist(DataModelException):
pass
class InvalidNamespaceAutoPrunePolicy(DataModelException):
pass
class InvalidNamespaceAutoPruneMethod(DataModelException):
pass
class InvalidNamespaceException(DataModelException):
pass
class RepositoryAutoPrunePolicyAlreadyExists(DataModelException):
pass
class RepositoryAutoPrunePolicyDoesNotExist(DataModelException):
pass
class InvalidRepositoryAutoPrunePolicy(DataModelException):
pass
class InvalidRepositoryAutoPruneMethod(DataModelException):
pass
class InvalidRepositoryException(DataModelException):
pass
class PushesDisabledException(Exception):
pass
class TooManyLoginAttemptsException(Exception):
def __init__(self, message, retry_after):
super(TooManyLoginAttemptsException, self).__init__(message)
self.retry_after = retry_after
class Config(object):
def __init__(self):
self.app_config = None
self.store = None
self.image_cleanup_callbacks = []
self.repo_cleanup_callbacks = []
def register_image_cleanup_callback(self, callback):
self.image_cleanup_callbacks.append(callback)
return lambda: self.image_cleanup_callbacks.remove(callback)
def register_repo_cleanup_callback(self, callback):
self.repo_cleanup_callbacks.append(callback)
return lambda: self.repo_cleanup_callbacks.remove(callback)
config = Config()
# There MUST NOT be any circular dependencies between these subsections. If there are fix it by
# moving the minimal number of things to _basequery
from data.model import (
appspecifictoken,
autoprune,
blob,
build,
entitlements,
gc,
label,
log,
message,
modelutil,
namespacequota,
notification,
oauth,
organization,
organization_skus,
permission,
proxy_cache,
release,
repo_mirror,
repository,
repositoryactioncount,
service_keys,
storage,
team,
token,
user,
)