Skip to content

Commit

Permalink
Fix the RepoMirrorConfig model to match the latest migrations
Browse files Browse the repository at this point in the history
RepoMirrorConfig in the current database migration version has a
non-null constraint on the internal_robot field, but the model in
database.py does not.

Updates the model to match the current database revision, and handles
the integrity errors accordingly when trying to delete the
RepoMirrorConfig robot.

Also set a default test DATABASE_SECRET_KEY when generating the test.db
  • Loading branch information
kleesc committed Aug 20, 2020
1 parent 0c65f88 commit e3e4c45
Show file tree
Hide file tree
Showing 6 changed files with 25 additions and 4 deletions.
4 changes: 3 additions & 1 deletion data/database.py
Expand Up @@ -1942,7 +1942,9 @@ class RepoMirrorConfig(BaseModel):
# Mirror Configuration
mirror_type = ClientEnumField(RepoMirrorType, default=RepoMirrorType.PULL)
internal_robot = QuayUserField(
allows_robots=True, null=True, backref="mirrorpullrobot", robot_null_delete=True
allows_robots=True, backref="mirrorpullrobot", robot_null_delete=True
# robot_null_delete is set so that deleting the robot does not delete this rule,
# but lets the db enforce the non-null constraint instead.
)
external_reference = CharField()
external_registry_username = EncryptedCharField(max_length=2048, null=True)
Expand Down
9 changes: 9 additions & 0 deletions data/model/test/test_repo_mirroring.py
Expand Up @@ -248,3 +248,12 @@ def test_release_mirror(initialized_db):
mirror = release_mirror(mirror, RepoMirrorStatus.FAIL)
assert mirror.sync_retries_remaining == 3
assert mirror.sync_start_date > original_sync_start_date


def test_delete_repo_mirror_robot(initialized_db):
mirror, _ = create_mirror_repo_robot(["updated", "created"], repo_name="first")
assert mirror
assert mirror.internal_robot

with pytest.raises(model.DataModelException):
model.user.delete_robot(mirror.internal_robot)
3 changes: 3 additions & 0 deletions data/model/user.py
Expand Up @@ -507,6 +507,9 @@ def delete_robot(robot_username):
except User.DoesNotExist:
raise InvalidRobotException("Could not find robot with username: %s" % robot_username)

except IntegrityError:
DataModelException("Could not delete robot with username: %s" % robot_username)


def list_namespace_robots(namespace):
"""
Expand Down
10 changes: 7 additions & 3 deletions endpoints/api/robot.py
Expand Up @@ -2,6 +2,7 @@
Manage user and organization robot accounts.
"""

from data.model import DataModelException
from endpoints.api import (
resource,
nickname,
Expand Down Expand Up @@ -141,9 +142,12 @@ def delete(self, robot_shortname):
Delete an existing robot.
"""
parent = get_authenticated_user()
model.delete_robot(format_robot_username(parent.username, robot_shortname))
log_action("delete_robot", parent.username, {"robot": robot_shortname})
return "", 204
try:
model.delete_robot(format_robot_username(parent.username, robot_shortname))
log_action("delete_robot", parent.username, {"robot": robot_shortname})
return "", 204
except DataModelException:
return "Conflict", 409


@resource("/v1/organization/<orgname>/robots")
Expand Down
3 changes: 3 additions & 0 deletions initdb.py
Expand Up @@ -17,6 +17,7 @@
from email.utils import formatdate
from data.database import (
db,
db_encrypter,
all_models,
Role,
TeamRole,
Expand Down Expand Up @@ -58,6 +59,7 @@
)
from data import model
from data.decorators import is_deprecated_model
from data.encryption import FieldEncrypter
from data.fields import Credential
from data.logs_model import logs_model
from data.queue import WorkQueue
Expand Down Expand Up @@ -293,6 +295,7 @@ def setup_database_for_testing(testcase):


def initialize_database():
db_encrypter.initialize(FieldEncrypter("anothercrazykey!"))
db.create_tables(all_models)

Role.create(name="admin")
Expand Down
Binary file modified test/data/test.db
Binary file not shown.

0 comments on commit e3e4c45

Please sign in to comment.