Skip to content

Commit

Permalink
Ensure unique relative path at validation time
Browse files Browse the repository at this point in the history
Checks the relative path of ostree distributors for conflicts.

closes #1106
  • Loading branch information
asmacdo committed Apr 6, 2016
1 parent 1d3874c commit 76ff7e2
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 11 deletions.
56 changes: 54 additions & 2 deletions plugins/pulp_ostree/plugins/distributors/configuration.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,32 @@
from gettext import gettext as _
import logging
import os

from pulp_ostree.common import constants

from mongoengine import Q
from pulp.server.db import model

_LOG = logging.getLogger(__name__)


def validate_config(config):
def validate_config(repo, config):
"""
Validate a configuration
:param repo: metadata describing the repository to which the configuration applies
:type repo: pulp.plugins.model.Repository
:param config: Pulp configuration for the distributor
:type config: pulp.plugins.config.PluginCallConfiguration
:raises: PulpCodedValidationException if any validations failed
:return: tuple of (bool, str) to describe the result
:rtype: tuple
"""
repo_obj = repo.repo_obj
relative_path = get_repo_relative_path(repo_obj, config)
error_msgs = _check_for_relative_path_conflicts(repo_obj.repo_id, relative_path)

if error_msgs:
return False, '\n'.join(error_msgs)

return True, None

Expand Down Expand Up @@ -83,3 +96,42 @@ def get_repo_relative_path(repo, config):
else:
path = repo.repo_id
return path


def _check_for_relative_path_conflicts(repo_id, relative_path):
"""
Check that a relative path does not conflict with existing distributors' relative paths.
:param repo_id: identifier of repository associated with the path to check
:type repo_id: basestring
:param relative_path: relative path of the repository
:type relative_path: basestring
:return error_messages: a list of validation errors
:rtype: list
"""
current_url_pieces = [x for x in relative_path.split('/') if x]
matching_url_list = []
working_url = ''
for piece in current_url_pieces:
working_url = os.path.join(working_url, piece)
matching_url_list.append(working_url)
matching_url_list.append('/' + working_url)

# Search for all the sub urls as well as any url that would fall within the specified url.
# The regex here basically matches the a url if it starts with (optional preceding slash)
# the working url. Anything can follow as long as it is separated by a slash.
rel_url_match = Q(config__relative_path={'$regex': '^/?' + working_url + '(/.*|/?\z)'})
rel_url_in_list = Q(config__relative_path__in=matching_url_list)

conflicts = model.Distributor.objects(rel_url_match | rel_url_in_list).only('repo_id', 'config')
error_messages = []
for distributor in conflicts:
conflicting_repo_id = distributor['repo_id']
conflicting_relative_url = None
conflicting_relative_url = distributor['config']['relative_path']
msg = _('Relative path [{relative_path}] for repository [{repo_id}] conflicts with '
'existing relative path [{conflict_url}] for repository [{conflict_repo}]')
error_messages.append(msg.format(relative_path=relative_path, repo_id=repo_id,
conflict_url=conflicting_relative_url,
conflict_repo=conflicting_repo_id))
return error_messages
2 changes: 1 addition & 1 deletion plugins/pulp_ostree/plugins/distributors/web.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,4 +161,4 @@ def validate_config(self, repo, config, config_conduit):
:raises: PulpCodedValidationException if any validations failed
"""
return configuration.validate_config(config)
return configuration.validate_config(repo, config)
13 changes: 7 additions & 6 deletions plugins/test/unit/plugins/distributors/test_configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
import tempfile
import unittest

from mock import Mock

import mock
from pulp.plugins.config import PluginCallConfiguration

from pulp_ostree.common import constants
Expand All @@ -18,7 +17,7 @@ def setUp(self):
self.publish_dir = os.path.join(self.working_directory, 'publish')
self.repo_working = os.path.join(self.working_directory, 'work')

self.repo = Mock(id='foo', working_dir=self.repo_working)
self.repo = mock.Mock(id='foo', working_dir=self.repo_working)
self.config = PluginCallConfiguration({constants.DISTRIBUTOR_CONFIG_KEY_PUBLISH_DIRECTORY:
self.publish_dir}, {})

Expand Down Expand Up @@ -50,9 +49,11 @@ def test_get_repo_relative_path_when_passed(self):
self.assertEquals(directory, relative_path[1:])


@mock.patch('pulp_ostree.plugins.distributors.configuration.model.Distributor.objects')
class TestValidateConfig(unittest.TestCase):

def test_server_url_fully_qualified(self):
def test_server_url_fully_qualified(self, mock_dist_qs):
m_repo = mock.MagicMock()
config = PluginCallConfiguration({}, {})
self.assertEquals((True, None),
configuration.validate_config(config))
self.assertEquals(
(True, None), configuration.validate_config(m_repo, config))
5 changes: 3 additions & 2 deletions plugins/test/unit/plugins/distributors/test_web.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ def test_cancel_publish_repo(self):

@patch('pulp_ostree.plugins.distributors.web.configuration.validate_config')
def test_validate_config(self, mock_validate):
value = self.distributor.validate_config(Mock(), 'foo', Mock())
mock_validate.assert_called_once_with('foo')
m_repo = Mock()
value = self.distributor.validate_config(m_repo, 'foo', Mock())
mock_validate.assert_called_once_with(m_repo, 'foo')
self.assertEquals(value, mock_validate.return_value)

0 comments on commit 76ff7e2

Please sign in to comment.