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

Add edit support for some legacyrole fields. #1943

Merged
merged 4 commits into from
Oct 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 44 additions & 4 deletions galaxy_ng/app/api/v1/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,15 @@ def get_summary_fields(self, obj):
'pulp_href': pulp_href
}

# FIXME - repository is a bit hacky atm
repository = {}
if obj.full_metadata.get('repository'):
repository = obj.full_metadata.get('repository')
if not repository.get('name'):
repository['name'] = obj.full_metadata.get('github_repo')
if not repository.get('original_name'):
repository['original_name'] = obj.full_metadata.get('github_repo')

return {
'dependencies': dependencies,
'namespace': {
Expand All @@ -321,10 +330,7 @@ def get_summary_fields(self, obj):
'avatar_url': f'https://github.com/{obj.namespace.name}.png'
},
'provider_namespace': provider_ns,
'repository': {
'name': obj.name,
'original_name': obj.full_metadata.get('github_repo')
},
'repository': repository,
'tags': tags,
'versions': versions
}
Expand All @@ -336,6 +342,40 @@ def get_download_count(self, obj):
return 0


class LegacyRoleRepositoryUpdateSerializer(serializers.Serializer):
name = serializers.CharField(required=False, allow_blank=False, max_length=50)
original_name = serializers.CharField(required=False, allow_blank=False, max_length=50)
Copy link
Contributor

@jerabekjiri jerabekjiri Oct 31, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm able to edit original_name in the repository, is that intended?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good question. I think longterm, no you shouldn't be able to. For the short term though, we need to be able to set that based on the old api data.


def is_valid(self, raise_exception=False):
# Check for any unexpected fields
extra_fields = set(self.initial_data.keys()) - set(self.fields.keys())
if extra_fields:
self._errors = {field: ["Unexpected field."] for field in extra_fields}
else:
# Continue with the original validation logic
super(serializers.Serializer, self).is_valid(raise_exception=raise_exception)

return not bool(self._errors)


class LegacyRoleUpdateSerializer(serializers.Serializer):
github_user = serializers.CharField(required=False, allow_blank=False, max_length=50)
github_repo = serializers.CharField(required=False, allow_blank=False, max_length=50)
github_branch = serializers.CharField(required=False, allow_blank=False, max_length=50)
repository = LegacyRoleRepositoryUpdateSerializer(required=False)

def is_valid(self, raise_exception=False):
# Check for any unexpected fields
extra_fields = set(self.initial_data.keys()) - set(self.fields.keys())
if extra_fields:
self._errors = {field: ["Unexpected field."] for field in extra_fields}
else:
# Continue with the original validation logic
super(serializers.Serializer, self).is_valid(raise_exception=raise_exception)

return not bool(self._errors)


class LegacyRoleContentSerializer(serializers.ModelSerializer):

readme = serializers.SerializerMethodField()
Expand Down
2 changes: 1 addition & 1 deletion galaxy_ng/app/api/v1/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@

path(
'roles/<int:pk>/',
LegacyRolesViewSet.as_view({"get": "retrieve", "delete": "destroy"}),
LegacyRolesViewSet.as_view({"get": "retrieve", "delete": "destroy", "put": "update"}),
name='legacy_role-detail'
),

Expand Down
51 changes: 51 additions & 0 deletions galaxy_ng/app/api/v1/viewsets/roles.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

from rest_framework import mixins
from rest_framework import viewsets
from rest_framework import status
from rest_framework.response import Response
from rest_framework.settings import perform_import
from rest_framework.pagination import PageNumberPagination
Expand All @@ -24,6 +25,7 @@
from galaxy_ng.app.api.v1.serializers import (
LegacyImportSerializer,
LegacyRoleSerializer,
LegacyRoleUpdateSerializer,
LegacyRoleContentSerializer,
LegacyRoleVersionsSerializer,
)
Expand Down Expand Up @@ -94,6 +96,55 @@ def list(self, request):

return super().list(request)

def update(self, request, pk=None):
role = self.get_object()
serializer = LegacyRoleUpdateSerializer(role, data=request.data, partial=True)
if not serializer.is_valid():
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

changed = {}
for key, newval in serializer.validated_data.items():

# repositories are special ...
if key == 'repository':
if not role.full_metadata.get('repository'):
changed['repository'] = {}
role.full_metadata['repository'] = {}
for subkey, subval in newval.items():
if role.full_metadata.get(key, {}).get(subkey) != subval:
if key not in changed:
changed[key] = {}
role.full_metadata[key][subkey] = subval
changed[key][subkey] = subval
continue

# github_repo should set repository.name?
if key == 'github_repo':
if not role.full_metadata.get('repository'):
changed['repository'] = {}
role.full_metadata['repository'] = {}
old_name = role.full_metadata['repository'].get('name')
role.full_metadata['repository']['name'] = newval
role.full_metadata['repository']['original_name'] = old_name

if role.full_metadata.get(key) != newval:
role.full_metadata[key] = newval
changed[key] = newval

# TODO - get rid of github_reference?
if key == 'github_branch':
key = 'github_reference'
if role.full_metadata.get(key) != newval:
role.full_metadata[key] = newval
changed[key] = newval

# only save if changes made
if changed:
role.save()
return Response(changed, status=200)

return Response(changed, status=204)

def destroy(self, request, pk=None):
"""Delete a single role."""
role = LegacyRole.objects.filter(id=pk).first()
Expand Down
133 changes: 133 additions & 0 deletions galaxy_ng/tests/integration/community/test_role_edits.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import pytest

# from ..utils import ansible_galaxy, get_client, SocialGithubClient
from ..utils import ansible_galaxy, get_client
from ..utils.legacy import clean_all_roles, cleanup_social_user


@pytest.mark.deployment_community
def test_community_legacy_role_edit(ansible_config):

# namespace_name = painless
# github_user = painless-software
# github_repository = ansible-role-software
# role_name = software
# install fqn = painless.software
# github_branch = main

admin_config = ansible_config("admin")
admin_client = get_client(
config=admin_config,
request_token=False,
require_auth=True
)

namespace_v3name = 'jctannertest'
namespace_v1name = 'jctannerTEST'
github_user = 'jctannerTEST'
github_repo = 'role1'
role_name = 'role1'
branch = 'master'

# cleanup
clean_all_roles(ansible_config)
cleanup_social_user(namespace_v3name, ansible_config)
cleanup_social_user(namespace_v1name, ansible_config)

# creat the v3 namespace
v3_ns = admin_client(
'/api/_ui/v1/namespaces/', method='POST', args={'name': namespace_v3name, 'groups': []}
)
assert v3_ns['name'] == namespace_v3name, v3_ns

# make the legacy ns
v1_ns = admin_client('/api/v1/namespaces/', method='POST', args={'name': namespace_v1name})
assert v1_ns['name'] == namespace_v1name, v1_ns

# bind the v3 namespace to the v1 namespace
v3_bind = {
'id': v3_ns['id']
}
admin_client(f"/api/v1/namespaces/{v1_ns['id']}/providers/", method='POST', args=v3_bind)

# import jctanerTEST role1
pid = ansible_galaxy(
f"role import {github_user} {github_repo} --branch={branch}",
ansible_config=admin_config,
force_token=True,
cleanup=False,
check_retcode=False
)
assert pid.returncode == 0, pid.stdout.decode('utf-8')

# find the new role ...
resp = admin_client(f'/api/v1/roles/?owner__username={namespace_v1name}&name={role_name}')
assert resp['count'] == 1
role = resp['results'][0]
assert role['summary_fields']['namespace']['name'] == namespace_v1name
assert role['summary_fields']['provider_namespace']['name'] == namespace_v3name
assert role['name'] == role_name
assert role['github_user'] == github_user
assert role['github_repo'] == github_repo
assert role['github_branch'] == branch

role_id = role['id']

# change the branch ...
admin_client(
f'/api/v1/roles/{role_id}/',
method='PUT',
args={'github_branch': 'fakebranch'}
)
newds = admin_client(f'/api/v1/roles/{role_id}/')
assert newds['github_branch'] == 'fakebranch'

# change the github_user ...
admin_client(
f'/api/v1/roles/{role_id}/',
method='PUT',
args={'github_user': 'fakeuser'}
)
newds = admin_client(f'/api/v1/roles/{role_id}/')
assert newds['github_user'] == 'fakeuser'

# change the github_repo ...
admin_client(
f'/api/v1/roles/{role_id}/',
method='PUT',
args={'github_repo': 'fakerepo'}
)
newds = admin_client(f'/api/v1/roles/{role_id}/')
assert newds['github_repo'] == 'fakerepo'

# change the repository.name ...
admin_client(
f'/api/v1/roles/{role_id}/',
method='PUT',
args={
'repository': {
'name': 'foorepo'
}
}
)
newds = admin_client(f'/api/v1/roles/{role_id}/')
assert newds['summary_fields']['repository']['name'] == 'foorepo'

# change the repository.original_name ...
admin_client(
f'/api/v1/roles/{role_id}/',
method='PUT',
args={
'repository': {
'original_name': 'foorepo_old'
}
}
)
newds = admin_client(f'/api/v1/roles/{role_id}/')
assert newds['summary_fields']['repository']['original_name'] == 'foorepo_old'

# cleanup the role ...
try:
admin_client(f'/api/v1/roles/{role_id}/', method='DELETE')
except Exception:
pass
Loading