Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Namespace Error / Namespace Ignored #2895

Open
luckylinux opened this issue Jun 16, 2024 · 7 comments
Open

Namespace Error / Namespace Ignored #2895

luckylinux opened this issue Jun 16, 2024 · 7 comments

Comments

@luckylinux
Copy link

luckylinux commented Jun 16, 2024

Description of the problem, including code/CLI snippet

I am getting started with this Library and most Things work quite well.

I cannot say the same about the Namespace/Groups though.

Code according to the Documentation:

    # Get Group / $Namespace ID based on Kernel
    group_id = gl.groups.list(search=minion_kernel)[0].id

    # If no Projects are found
    if not search_project:
       # Echo
       print(f"\t Create new Project {minion_name} in Namespace {minion_kernel} (Group ID {group_id})")

       # Create a new Project
       new_project = current_user.projects.create({
                                                   "name": minion_name ,
                                                   "path": minion_name ,
                                                   "namespace_id": int(group_id)
                                                  })

    # Update Project
    current_project = gl.projects.list(name=minion_name , namespace=minion_kernel , get_all=True)[0]

    print(current_project)

Result:

	 Create new Project backup01 in Namespace linux (Group ID 5)
Traceback (most recent call last):
  File "/opt/gitlab-python/lib/python3.11/site-packages/gitlab/exceptions.py", line 340, in wrapped_f
    return f(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^
  File "/opt/gitlab-python/lib/python3.11/site-packages/gitlab/mixins.py", line 301, in create
    server_data = self.gitlab.http_post(path, post_data=data, files=files, **kwargs)
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/gitlab-python/lib/python3.11/site-packages/gitlab/client.py", line 1000, in http_post
    result = self.http_request(
             ^^^^^^^^^^^^^^^^^^
  File "/opt/gitlab-python/lib/python3.11/site-packages/gitlab/client.py", line 793, in http_request
    raise gitlab.exceptions.GitlabHttpError(
gitlab.exceptions.GitlabHttpError: 400: {'namespace': ['is not valid']}

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/srv/scripts-nas/gitlab/./setup_gitconfigbackup_api.py", line 212, in <module>
    setup_minion(id=minion , kernel=kernel)
  File "/srv/scripts-nas/gitlab/./setup_gitconfigbackup_api.py", line 162, in setup_minion
    new_project = current_user.projects.create({
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/gitlab-python/lib/python3.11/site-packages/gitlab/exceptions.py", line 342, in wrapped_f
    raise error(e.error_message, e.response_code, e.response_body) from e
gitlab.exceptions.GitlabCreateError: 400: {'namespace': ['is not valid']}

If I use namespace instead of namespace_id:

    # Get Group / $Namespace ID based on Kernel
    group_id = gl.groups.list(search=minion_kernel)[0].id

    # If no Projects are found
    if not search_project:
       # Echo
       print(f"\t Create new Project {minion_name} in Namespace {minion_kernel} (Group ID {group_id})")

       # Create a new Project
       new_project = current_user.projects.create({
                                                   "name": minion_name ,
                                                   "path": minion_name ,
                                                   "namespace": minion_kernel
                                                  })

    # Update Project
    current_project = gl.projects.list(name=minion_name , namespace=minion_kernel , get_all=True)[0]

    print(current_project)

Then I get:

	 Create new Project backup01 in Namespace linux (Group ID 5)
<class 'gitlab.v4.objects.projects.Project'> => {'id': 81, 'description': None, 'name': 'backup01', 'name_with_namespace': 'backup01 / backup01', 'path': 'backup01', 'path_with_namespace': 'backup01/backup01', 'created_at': '2024-06-16T18:37:10.670Z', 'default_branch': 'main', 'tag_list': [], 'topics': [], 'ssh_url_to_repo': 'gitconfigbackup-server@gitconfigbackup.MYDOMAIN.TLD:backup01/backup01.git', 'http_url_to_repo': 'https://gitconfigbackup.MYDOMAIN.TLD/backup01/backup01.git', 'web_url': 'https://gitconfigbackup.MYDOMAIN.TLD/backup01/backup01', 'readme_url': None, 'forks_count': 0, 'avatar_url': None, 'star_count': 0, 'last_activity_at': '2024-06-16T18:37:10.629Z', 'namespace': {'id': 112, 'name': 'backup01', 'path': 'backup01', 'kind': 'user', 'full_path': 'backup01', 'parent_id': None, 'avatar_url': 'https://secure.gravatar.com/avatar/59fbdfd1a3557aae106cdac5ada63c6277ad381f8e3cfe740286098da9675438?s=80&d=identicon', 'web_url': 'https://gitconfigbackup.MYDOMAIN.TLD/backup01'}, 'repository_storage': 'default', '_links': {'self': 'https://gitconfigbackup.MYDOMAIN.TLD/api/v4/projects/81', 'issues': 'https://gitconfigbackup.MYDOMAIN.TLD/api/v4/projects/81/issues', 'merge_requests': 'https://gitconfigbackup.MYDOMAIN.TLD/api/v4/projects/81/merge_requests', 'repo_branches': 'https://gitconfigbackup.MYDOMAIN.TLD/api/v4/projects/81/repository/branches', 'labels': 'https://gitconfigbackup.MYDOMAIN.TLD/api/v4/projects/81/labels', 'events': 'https://gitconfigbackup.MYDOMAIN.TLD/api/v4/projects/81/events', 'members': 'https://gitconfigbackup.MYDOMAIN.TLD/api/v4/projects/81/members', 'cluster_agents': 'https://gitconfigbackup.MYDOMAIN.TLD/api/v4/projects/81/cluster_agents'}, 'packages_enabled': True, 'empty_repo': True, 'archived': False, 'visibility': 'private', 'owner': {'id': 56, 'username': 'backup01', 'name': 'backup01', 'state': 'active', 'locked': False, 'avatar_url': 'https://secure.gravatar.com/avatar/59fbdfd1a3557aae106cdac5ada63c6277ad381f8e3cfe740286098da9675438?s=80&d=identicon', 'web_url': 'https://gitconfigbackup.MYDOMAIN.TLD/backup01'}, 'resolve_outdated_diff_discussions': False, 'container_expiration_policy': {'cadence': '1d', 'enabled': False, 'keep_n': 10, 'older_than': '90d', 'name_regex': '.*', 'name_regex_keep': None, 'next_run_at': '2024-06-17T18:37:10.680Z'}, 'repository_object_format': 'sha1', 'issues_enabled': True, 'merge_requests_enabled': True, 'wiki_enabled': True, 'jobs_enabled': True, 'snippets_enabled': True, 'container_registry_enabled': True, 'service_desk_enabled': False, 'service_desk_address': None, 'can_create_merge_request_in': True, 'issues_access_level': 'enabled', 'repository_access_level': 'enabled', 'merge_requests_access_level': 'enabled', 'forking_access_level': 'enabled', 'wiki_access_level': 'enabled', 'builds_access_level': 'enabled', 'snippets_access_level': 'enabled', 'pages_access_level': 'private', 'analytics_access_level': 'enabled', 'container_registry_access_level': 'enabled', 'security_and_compliance_access_level': 'private', 'releases_access_level': 'enabled', 'environments_access_level': 'enabled', 'feature_flags_access_level': 'enabled', 'infrastructure_access_level': 'enabled', 'monitor_access_level': 'enabled', 'model_experiments_access_level': 'enabled', 'model_registry_access_level': 'enabled', 'emails_disabled': False, 'emails_enabled': True, 'shared_runners_enabled': True, 'lfs_enabled': True, 'creator_id': 56, 'import_url': None, 'import_type': None, 'import_status': 'none', 'open_issues_count': 0, 'description_html': '', 'updated_at': '2024-06-16T18:37:10.670Z', 'ci_default_git_depth': 20, 'ci_forward_deployment_enabled': True, 'ci_forward_deployment_rollback_allowed': True, 'ci_job_token_scope_enabled': False, 'ci_separated_caches': True, 'ci_allow_fork_pipelines_to_run_in_parent_project': True, 'build_git_strategy': 'fetch', 'keep_latest_artifact': True, 'restrict_user_defined_variables': False, 'runners_token': None, 'runner_token_expiration_interval': None, 'group_runners_enabled': True, 'auto_cancel_pending_pipelines': 'enabled', 'build_timeout': 3600, 'auto_devops_enabled': True, 'auto_devops_deploy_strategy': 'continuous', 'ci_config_path': None, 'public_jobs': True, 'shared_with_groups': [], 'only_allow_merge_if_pipeline_succeeds': False, 'allow_merge_on_skipped_pipeline': None, 'request_access_enabled': True, 'only_allow_merge_if_all_discussions_are_resolved': False, 'remove_source_branch_after_merge': True, 'printing_merge_request_link_enabled': True, 'merge_method': 'merge', 'squash_option': 'default_off', 'enforce_auth_checks_on_uploads': True, 'suggestion_commit_message': None, 'merge_commit_template': None, 'squash_commit_template': None, 'issue_branch_template': None, 'warn_about_potentially_unwanted_characters': True, 'autoclose_referenced_issues': True, 'permissions': {'project_access': None, 'group_access': None}}

Expected Behavior

Able to create a Project in the Requested Namespace.

Actual Behavior

Either an Error Occurs (if Code is according to the Documentation), or the namespace is completely ignored and the name of the Project is used instead.

I attempted to fix this later by trying to Update the Project:

# Update Project
current_project = gl.projects.list(name=minion_name , namespace=minion_kernel , get_all=True)[0]

print(current_project)

# Attempt to Update Project
current_project.name = minion_name
current_project.path = minion_name
current_project.path_with_namespace = f"{minion_kernel}/{minion_name}"
current_project.namespace = minion_kernel
current_project.save()

This however would not do anything 😞.

Specifications

  • python-gitlab version: 4.6.0
  • API version you are using (v3/v4): Not sure (default ?)
  • Gitlab server version (or gitlab.com): self-hosted gitlab-ce 17.0.2-ce.0
@luckylinux
Copy link
Author

It's not correct in my view to do it like this, but after creating it I could in theory do:

new_project.transfer(to_namespace=group_id)

@JohnVillalovos
Copy link
Member

I don't know the answer to your question. But I do recommend looking at the upstream documentation as that is the source of truth for the API. https://docs.gitlab.com/ee/api/projects.html

That might have some info on what is going wrong.

@JohnVillalovos
Copy link
Member

Also using gl.enable_debug() can show the information being sent to the GitLab server. This can be useful in debugging the issue.

@luckylinux
Copy link
Author

luckylinux commented Jun 16, 2024

I guess the issue is that I try to create a new Project as a User (admin only).
My API Token has Admin Access, so that is NOT the Issue.

But maybe, by creating Project as a User, it will use the user's namespace only.

This works correctly:

       # Create a new Project
       new_project = gl.projects.create({
                                           "name": minion_name ,
                                           "path": minion_name ,
                                           "namespace_id": group_id
                                        })

But then of course I need to manually add the User Later:

member = project.members.create({'user_id': user.id, 'access_level':
                                 gitlab.const.AccessLevel.DEVELOPER})

And this has the additional Issue that the User will NOT be the owner of the Repository.

EDIT 1: Actually this might just be what I did previously using the now deprecated gitlab BASH API.

EDIT 2: Final Solution

# Update Project
current_project = gl.projects.list(name=minion_name , namespace=minion_kernel , get_all=True)[0]

# Check if User is already a member of the Project
search_member = current_project.members.list(query=minion_name , get_all=True)

if not search_member:
        # Add User with Maintainer Level Access
        member = current_project.members.create({
                                                  "user_id": user_id,
                                                  "access_level": gitlab.const.AccessLevel.MAINTAINER,
                                                })

# Update Member if Required
current_member = current_project.members.list(query=minion_name , get_all=True)[0]
current_member.access_level = gitlab.const.AccessLevel.MAINTAINER
current_member.save()


@JohnVillalovos
Copy link
Member

JohnVillalovos commented Jun 16, 2024

I think you got things working. If so I'm glad to hear that.

One thing I did notice in your very first example the code does say namespace_id but the error message said:

gitlab.exceptions.GitlabHttpError: 400: {'namespace': ['is not valid']}

Just pointing that out in case somehow namespace was being used instead of namespace_id.

And if the user create isn't working then maybe that is a bug upstream? With the enable_debug() you can see exactly what is being sent to GitLab. If you verify the correct information is being sent as they document the API then it would likely be an upstream bug. If the information is being sent incorrectly then it could be a python-gitlab issue.

@luckylinux
Copy link
Author

luckylinux commented Jun 17, 2024

@JohnVillalovos no, I was using namespace_id as per the Code / Documentation, which then prompted that namespace Error. That's why the Error made no sense whatsoever 😞.
I guess either the python-gitlab or upstream API was "jumping" between Tables (Users, Projects, Members).

When I used namespace, no Error is generated but it gets completely ignored (and the User's Namespace is used instead).

@JohnVillalovos
Copy link
Member

@luckylinux One thought. Is it possible the user doesn't have permissions to that namespace?

Also maybe print out the value that was received from:

group = gl.groups.list(search=minion_kernel)[0]
group.pprint()
group_id = group.id

In case the group was not the group you were expecting from the search.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants