diff --git a/cli/copr_cli/main.py b/cli/copr_cli/main.py index 605cf5cc8..54348cf85 100644 --- a/cli/copr_cli/main.py +++ b/cli/copr_cli/main.py @@ -485,6 +485,7 @@ def action_create(self, args): runtime_dependencies=args.runtime_dependencies, packit_forge_projects_allowed=args.packit_forge_projects_allowed, repo_priority=args.repo_priority, + storage=args.storage, ) owner_part = username.replace('@', "g/") @@ -1192,6 +1193,13 @@ def setup_parser(): help=("Use the priority= config option for repositories in this " "project, see man dnf.conf(5) for more info.")) + parser_create.add_argument( + "--storage", + choices=["backend", "pulp"], + help=("What storage should be used for this project. " + "This option can only be specified by a COPR admin.") + ) + create_and_modify_common_opts(parser_create) parser_create.set_defaults(func="action_create") diff --git a/cli/tests/test_cli.py b/cli/tests/test_cli.py index 98b7a70c7..3a98fe174 100644 --- a/cli/tests/test_cli.py +++ b/cli/tests/test_cli.py @@ -480,6 +480,7 @@ def test_create_project(config_from_file, project_proxy_add, capsys): "runtime_dependencies": None, "packit_forge_projects_allowed": None, "repo_priority": None, + "storage": None, } assert stdout == "New project was successfully created: http://copr/coprs/jdoe/foo/\n" @@ -577,6 +578,7 @@ def test_create_multilib_project(config_from_file, project_proxy_add, capsys): "runtime_dependencies": None, "packit_forge_projects_allowed": None, "repo_priority": None, + "storage": None, } assert stdout == "New project was successfully created: http://copr/coprs/jdoe/foo/\n" diff --git a/frontend/coprs_frontend/coprs/forms.py b/frontend/coprs_frontend/coprs/forms.py index cb5b457a3..894a86e29 100644 --- a/frontend/coprs_frontend/coprs/forms.py +++ b/frontend/coprs_frontend/coprs/forms.py @@ -676,6 +676,12 @@ class CoprForm(BaseForm): default=None, ) + storage = wtforms.SelectField( + "Admin only - what storage should be used for this project", + choices=[(x, x) for x in ["backend", "pulp"]], + validators=[wtforms.validators.Optional()], + ) + @property def errors(self): """ diff --git a/frontend/coprs_frontend/coprs/logic/coprs_logic.py b/frontend/coprs_frontend/coprs/logic/coprs_logic.py index 2922297ea..ed804f92b 100644 --- a/frontend/coprs_frontend/coprs/logic/coprs_logic.py +++ b/frontend/coprs_frontend/coprs/logic/coprs_logic.py @@ -287,7 +287,7 @@ def get_multiple_fulltext(cls, fulltext=None, projectname=None, def add(cls, user, name, selected_chroots, repos=None, description=None, instructions=None, check_for_duplicates=False, group=None, persistent=False, auto_prune=True, bootstrap=None, follow_fedora_branching=False, isolation=None, - appstream=False, **kwargs): + appstream=False, storage=None, **kwargs): if not flask.g.user.admin and flask.g.user != user: msg = ("You were authorized as '{0}' user without permissions to access " @@ -300,6 +300,10 @@ def add(cls, user, name, selected_chroots, repos=None, description=None, if not flask.g.user.admin and not auto_prune: raise exceptions.NonAdminCannotDisableAutoPrunning() + if not flask.g.user.admin and storage: + raise exceptions.AccessRestricted("Non-admin cannot set storage") + storage = StorageEnum(storage or app.config["DEFAULT_STORAGE"]) + # form validation checks for duplicates cls.new(user, name, group, check_for_duplicates=check_for_duplicates) @@ -315,7 +319,7 @@ def add(cls, user, name, selected_chroots, repos=None, description=None, isolation=isolation, follow_fedora_branching=follow_fedora_branching, appstream=appstream, - storage=StorageEnum(app.config["DEFAULT_STORAGE"]), + storage=storage, **kwargs) diff --git a/frontend/coprs_frontend/coprs/views/apiv3_ns/apiv3_projects.py b/frontend/coprs_frontend/coprs/views/apiv3_ns/apiv3_projects.py index 681016197..2084d0b1c 100644 --- a/frontend/coprs_frontend/coprs/views/apiv3_ns/apiv3_projects.py +++ b/frontend/coprs_frontend/coprs/views/apiv3_ns/apiv3_projects.py @@ -262,6 +262,7 @@ def _form_field_repos(form_field): form.packit_forge_projects_allowed ), repo_priority=form.repo_priority.data, + storage=form.storage.data, ) db.session.commit() except ( diff --git a/frontend/coprs_frontend/coprs/views/apiv3_ns/schema/schemas.py b/frontend/coprs_frontend/coprs/views/apiv3_ns/schema/schemas.py index cbb68bfd2..0a5eb706c 100644 --- a/frontend/coprs_frontend/coprs/views/apiv3_ns/schema/schemas.py +++ b/frontend/coprs_frontend/coprs/views/apiv3_ns/schema/schemas.py @@ -477,6 +477,13 @@ class _ProjectGetAddFields: description="Build and project is immune against deletion", ) additional_repos: List = fields.additional_repos + storage: String = String( + description=( + "Admin only - what storage should be used for this project. " + "Possible values are 'backend' or 'pulp'." + ), + ) + @dataclass diff --git a/frontend/coprs_frontend/tests/test_apiv3/test_projects.py b/frontend/coprs_frontend/tests/test_apiv3/test_projects.py index 89779c3d3..34ecf7927 100644 --- a/frontend/coprs_frontend/tests/test_apiv3/test_projects.py +++ b/frontend/coprs_frontend/tests/test_apiv3/test_projects.py @@ -5,7 +5,6 @@ import pytest -from copr_common.enums import StorageEnum from coprs.models import User, Copr from tests.coprs_test_case import CoprsTestCase, TransactionDecorator @@ -153,8 +152,6 @@ def test_update_copr_api3(self): }, { }, { "appstream": True, - }, { - "storage": StorageEnum("backend"), }] for setup in easy_changes: @@ -168,7 +165,7 @@ def test_update_copr_api3(self): "created_on", "deleted", "scm_api_auth_json", "scm_api_type", "scm_repo_url", "id", "name", "user_id", "group_id", "webhook_secret", "forked_from_id", "latest_indexed_data_update", - "copr_id", "persistent", "playground", + "copr_id", "persistent", "playground", "storage", ]: should_test.remove(item) diff --git a/python/copr/v3/proxies/project.py b/python/copr/v3/proxies/project.py index ece6d13cc..69ba81d5f 100644 --- a/python/copr/v3/proxies/project.py +++ b/python/copr/v3/proxies/project.py @@ -72,7 +72,7 @@ def add(self, ownername, projectname, chroots, description=None, instructions=No delete_after_days=None, multilib=False, module_hotfixes=False, bootstrap=None, bootstrap_image=None, isolation=None, follow_fedora_branching=True, fedora_review=None, appstream=False, runtime_dependencies=None, packit_forge_projects_allowed=None, - repo_priority=None, exist_ok=False): + repo_priority=None, exist_ok=False, storage=None): """ Create a project @@ -110,6 +110,7 @@ def add(self, ownername, projectname, chroots, description=None, instructions=No enabled together with this project repository. :param list packit_forge_projects_allowed: List of forge projects that will be allowed to build in the project via Packit + :param str storage: Admin only - What storage should be used for this project :return: Munch """ endpoint = "/project/add/{ownername}" @@ -142,6 +143,7 @@ def add(self, ownername, projectname, chroots, description=None, instructions=No "runtime_dependencies": runtime_dependencies, "packit_forge_projects_allowed": packit_forge_projects_allowed, "repo_priority": repo_priority, + "storage": storage, } _compat_use_bootstrap_container(data, use_bootstrap_container)