Esempio n. 1
0
    def test_bind_failed(self, mock_bind):

        # Setup
        self.populate()

        # Test
        options = {}
        itinerary = bind_itinerary(
            self.CONSUMER_ID,
            self.REPO_ID,
            self.DISTRIBUTOR_ID,
            self.NOTIFY_AGENT,
            self.BINDING_CONFIG,
            options)
        call_reports = self.coordinator.execute_multiple_calls(itinerary)

        # Verify
        self.assertEqual(len(call_reports), 2)
        for call in call_reports:
            self.assertNotEqual(call.state, dispatch_constants.CALL_REJECTED_RESPONSE)

        # run task #1 (actual bind)
        self.run_next()

        # run task #2 (notify consumer)
        self.run_next()

        # verify task #2 was skipped
        request_id = call_reports[1].call_request_id
        call_report = self.coordinator.find_call_reports(call_request_id=request_id)[0]
        self.assertEqual(call_report.state, dispatch_constants.CALL_SKIPPED_STATE)

        # verify agent NOT notified
        self.assertFalse(mock_agent.Consumer.bind.called)
Esempio n. 2
0
    def test_bind(self):

        # Setup
        self.populate()

        # Test
        options = {}
        itinerary = bind_itinerary(
            self.CONSUMER_ID,
            self.REPO_ID,
            self.DISTRIBUTOR_ID,
            self.NOTIFY_AGENT,
            self.BINDING_CONFIG,
            options)
        call_reports = self.coordinator.execute_multiple_calls(itinerary)

        # Verify
        self.assertEqual(len(call_reports), 2)
        self.assertEqual(call_reports[0].call_request_tags, self.BIND_TAGS)
        self.assertEqual(call_reports[1].call_request_tags, self.AGENT_BIND_TAGS)
        for call in call_reports:
            self.assertNotEqual(call.state, dispatch_constants.CALL_REJECTED_RESPONSE)

        # run task #1 (actual bind)
        self.run_next()

        # verify bind created
        manager = factory.consumer_bind_manager()
        binds = manager.find_by_consumer(self.CONSUMER_ID)
        self.assertEquals(len(binds), 1)
        bind = binds[0]
        self.assertEqual(bind['consumer_id'], self.CONSUMER_ID)
        self.assertEqual(bind['repo_id'], self.REPO_ID)
        self.assertEqual(bind['distributor_id'], self.DISTRIBUTOR_ID)
        self.assertEqual(bind['notify_agent'], self.NOTIFY_AGENT)
        self.assertEqual(bind['binding_config'], self.BINDING_CONFIG)

        # run task #2 (notify consumer)
        self.run_next()

        # verify pending consumer request (pending)
        request_id = call_reports[1].call_request_id
        bind = manager.get_bind(self.CONSUMER_ID, self.REPO_ID, self.DISTRIBUTOR_ID)
        actions = bind['consumer_actions']
        self.assertEqual(len(actions), 1)
        self.assertEqual(actions[0]['id'], request_id)
        self.assertEqual(actions[0]['action'], Bind.Action.BIND)
        self.assertEqual(actions[0]['status'], Bind.Status.PENDING)
        self.assertTrue(isinstance(actions[0]['timestamp'], float))

        # verify agent notified
        self.assertTrue(mock_agent.Consumer.bind.called)
        # simulated asynchronous task result
        report = DispatchReport()
        self.coordinator.complete_call_success(request_id, report.dict())

        # verify pending consumer request (confirmed)
        manager = factory.consumer_bind_manager()
        bind = manager.get_bind(self.CONSUMER_ID, self.REPO_ID, self.DISTRIBUTOR_ID)
        self.assertEqual(len(bind['consumer_actions']), 0)
Esempio n. 3
0
    def POST(self, consumer_id):
        """
        Create a bind association between the specified
        consumer by id included in the URL path and a repo-distributor
        specified in the POST body: {repo_id:<str>, distributor_id:<str>}.
        Designed to be idempotent so only MissingResource is expected to
        be raised by manager.
        @param consumer_id: The consumer to bind.
        @type consumer_id: str
        @return: The list of call_reports
        @rtype: list
        """
        # validate consumer
        consumer_manager = managers.consumer_manager()
        consumer_manager.get_consumer(consumer_id)

        # get other options and validate them
        body = self.params()
        repo_id = body.get('repo_id')
        distributor_id = body.get('distributor_id')
        binding_config = body.get('binding_config', None)
        options = body.get('options', {})
        notify_agent = body.get('notify_agent', True)

        managers.repo_query_manager().get_repository(repo_id)
        managers.repo_distributor_manager().get_distributor(
            repo_id, distributor_id)

        # bind
        call_requests = bind_itinerary(consumer_id, repo_id, distributor_id,
                                       notify_agent, binding_config, options)
        execution.execute_multiple(call_requests)
Esempio n. 4
0
    def POST(self, consumer_id):
        """
        Create a bind association between the specified
        consumer by id included in the URL path and a repo-distributor
        specified in the POST body: {repo_id:<str>, distributor_id:<str>}.
        Designed to be idempotent so only MissingResource is expected to
        be raised by manager.
        @param consumer_id: The consumer to bind.
        @type consumer_id: str
        @return: The list of call_reports
        @rtype: list
        """
        # validate consumer
        consumer_manager = managers.consumer_manager()
        consumer_manager.get_consumer(consumer_id)

        # get other options and validate them
        body = self.params()
        repo_id = body.get('repo_id')
        distributor_id = body.get('distributor_id')
        binding_config = body.get('binding_config', None)
        options = body.get('options', {})
        notify_agent = body.get('notify_agent', True)

        managers.repo_query_manager().get_repository(repo_id)
        managers.repo_distributor_manager().get_distributor(repo_id, distributor_id)

        # bind
        call_requests = bind_itinerary(consumer_id, repo_id, distributor_id, notify_agent, binding_config, options)
        execution.execute_multiple(call_requests)
Esempio n. 5
0
    def test_bind_failed(self, mock_bind):

        # Setup
        self.populate()

        # Test
        options = {}
        itinerary = bind_itinerary(
            self.CONSUMER_ID,
            self.REPO_ID,
            self.DISTRIBUTOR_ID,
            self.NOTIFY_AGENT,
            self.BINDING_CONFIG,
            options)
        call_reports = self.coordinator.execute_multiple_calls(itinerary)

        # Verify
        self.assertEqual(len(call_reports), 2)
        for call in call_reports:
            self.assertNotEqual(call.state, dispatch_constants.CALL_REJECTED_RESPONSE)

        # run task #1 (actual bind)
        self.run_next()

        # run task #2 (notify consumer)
        self.run_next()

        # verify task #2 was skipped
        request_id = call_reports[1].call_request_id
        call_report = self.coordinator.find_call_reports(call_request_id=request_id)[0]
        self.assertEqual(call_report.state, dispatch_constants.CALL_SKIPPED_STATE)

        # verify agent NOT notified
        self.assertFalse(mock_agent.Consumer.bind.called)
Esempio n. 6
0
def consumer_group_bind_itinerary(group_id, repo_id, distributor_id,
                                  notify_agent, binding_config, agent_options):
    """
    Bind the members of the specified consumer group.
    :param group_id: A consumer group ID.
    :type group_id: str
    :param repo_id: A repository ID.
    :type repo_id: str
    :param distributor_id: A distributor ID.
    :type distributor_id: str
    :param agent_options: Bind options passed to the agent handler.
    :type agent_options: dict
    :param notify_agent: indicates if the agent should be sent a message about the new binding
    :type  notify_agent: bool
    :param binding_config: configuration options to use when generating the payload for this binding
    :type binding_config: dict
    :return: A list of call_requests.
    :rtype list
    """
    call_requests = []
    manager = managers.consumer_group_query_manager()
    group = manager.get_group(group_id)
    for consumer_id in group['consumer_ids']:
        itinerary = bind_itinerary(consumer_id=consumer_id,
                                   repo_id=repo_id,
                                   distributor_id=distributor_id,
                                   notify_agent=notify_agent,
                                   binding_config=binding_config,
                                   agent_options=agent_options)
        call_requests.extend(itinerary)
    return call_requests
Esempio n. 7
0
    def test_bind(self):

        # Setup
        self.populate()

        # Test
        options = {}
        itinerary = bind_itinerary(
            self.CONSUMER_ID,
            self.REPO_ID,
            self.DISTRIBUTOR_ID,
            self.NOTIFY_AGENT,
            self.BINDING_CONFIG,
            options)
        call_reports = self.coordinator.execute_multiple_calls(itinerary)

        # Verify
        self.assertEqual(len(call_reports), 2)
        self.assertEqual(call_reports[0].call_request_tags, self.BIND_TAGS)
        self.assertEqual(call_reports[1].call_request_tags, self.AGENT_BIND_TAGS)
        for call in call_reports:
            self.assertNotEqual(call.state, dispatch_constants.CALL_REJECTED_RESPONSE)

        # run task #1 (actual bind)
        self.run_next()

        # verify bind created
        manager = factory.consumer_bind_manager()
        binds = manager.find_by_consumer(self.CONSUMER_ID)
        self.assertEquals(len(binds), 1)
        bind = binds[0]
        self.assertEqual(bind['consumer_id'], self.CONSUMER_ID)
        self.assertEqual(bind['repo_id'], self.REPO_ID)
        self.assertEqual(bind['distributor_id'], self.DISTRIBUTOR_ID)
        self.assertEqual(bind['notify_agent'], self.NOTIFY_AGENT)
        self.assertEqual(bind['binding_config'], self.BINDING_CONFIG)

        # run task #2 (notify consumer)
        self.run_next()

        # verify pending consumer request (pending)
        request_id = call_reports[1].call_request_id
        bind = manager.get_bind(self.CONSUMER_ID, self.REPO_ID, self.DISTRIBUTOR_ID)
        actions = bind['consumer_actions']
        self.assertEqual(len(actions), 1)
        self.assertEqual(actions[0]['id'], request_id)
        self.assertEqual(actions[0]['action'], Bind.Action.BIND)
        self.assertEqual(actions[0]['status'], Bind.Status.PENDING)
        self.assertTrue(isinstance(actions[0]['timestamp'], float))

        # verify agent notified
        self.assertTrue(mock_agent.Consumer.bind.called)
        # simulated asynchronous task result
        report = DispatchReport()
        self.coordinator.complete_call_success(request_id, report.dict())

        # verify pending consumer request (confirmed)
        manager = factory.consumer_bind_manager()
        bind = manager.get_bind(self.CONSUMER_ID, self.REPO_ID, self.DISTRIBUTOR_ID)
        self.assertEqual(len(bind['consumer_actions']), 0)
Esempio n. 8
0
def consumer_group_bind_itinerary(group_id, repo_id, distributor_id, notify_agent, binding_config, agent_options):
    """
    Bind the members of the specified consumer group.
    :param group_id: A consumer group ID.
    :type group_id: str
    :param repo_id: A repository ID.
    :type repo_id: str
    :param distributor_id: A distributor ID.
    :type distributor_id: str
    :param agent_options: Bind options passed to the agent handler.
    :type agent_options: dict
    :param notify_agent: indicates if the agent should be sent a message about the new binding
    :type  notify_agent: bool
    :param binding_config: configuration options to use when generating the payload for this binding
    :type binding_config: dict
    :return: A list of call_requests.
    :rtype list
    """
    call_requests = []
    manager = managers.consumer_group_query_manager()
    group = manager.get_group(group_id)
    for consumer_id in group["consumer_ids"]:
        itinerary = bind_itinerary(
            consumer_id=consumer_id,
            repo_id=repo_id,
            distributor_id=distributor_id,
            notify_agent=notify_agent,
            binding_config=binding_config,
            agent_options=agent_options,
        )
        call_requests.extend(itinerary)
    return call_requests
Esempio n. 9
0
def distributor_update_itinerary(repo_id, distributor_id, config):
    """
    Get the itinerary for updating a repository distributor.
      1. Update the distributor on the sever.
      2. (re)bind any bound consumers.
    @param repo_id: A repository ID.
    @type repo_id: str
    @return: A list of call_requests known as an itinerary.
    @rtype list
    """

    call_requests = []

    # update the distributor

    manager = managers.repo_distributor_manager()
    resources = {
        dispatch_constants.RESOURCE_REPOSITORY_TYPE: {repo_id: dispatch_constants.RESOURCE_UPDATE_OPERATION},
        dispatch_constants.RESOURCE_REPOSITORY_DISTRIBUTOR_TYPE: {
            distributor_id: dispatch_constants.RESOURCE_UPDATE_OPERATION
        },
    }

    tags = [
        resource_tag(dispatch_constants.RESOURCE_REPOSITORY_TYPE, repo_id),
        resource_tag(dispatch_constants.RESOURCE_REPOSITORY_DISTRIBUTOR_TYPE, distributor_id),
        action_tag("update_distributor"),
    ]

    update_request = CallRequest(
        manager.update_distributor_config,
        [repo_id, distributor_id],
        {"distributor_config": config},
        resources=resources,
        tags=tags,
        archive=True,
        kwarg_blacklist=["distributor_config"],
    )

    call_requests.append(update_request)

    # append unbind itineraries foreach bound consumer

    options = {}
    manager = managers.consumer_bind_manager()
    for bind in manager.find_by_distributor(repo_id, distributor_id):
        bind_requests = bind_itinerary(
            bind["consumer_id"],
            bind["repo_id"],
            bind["distributor_id"],
            bind["notify_agent"],
            bind["binding_config"],
            options,
        )
        if bind_requests:
            bind_requests[0].depends_on(update_request.id)
            call_requests.extend(bind_requests)

    return call_requests
Esempio n. 10
0
def distributor_update_itinerary(repo_id, distributor_id, config):
    """
    Get the itinerary for updating a repository distributor.
      1. Update the distributor on the sever.
      2. (re)bind any bound consumers.
    @param repo_id: A repository ID.
    @type repo_id: str
    @return: A list of call_requests known as an itinerary.
    @rtype list
    """

    call_requests = []

    # update the distributor

    manager = managers.repo_distributor_manager()
    resources = {
        dispatch_constants.RESOURCE_REPOSITORY_TYPE: {
            repo_id: dispatch_constants.RESOURCE_UPDATE_OPERATION
        },
        dispatch_constants.RESOURCE_REPOSITORY_DISTRIBUTOR_TYPE: {
            distributor_id: dispatch_constants.RESOURCE_UPDATE_OPERATION
        }
    }

    tags = [
        resource_tag(dispatch_constants.RESOURCE_REPOSITORY_TYPE, repo_id),
        resource_tag(dispatch_constants.RESOURCE_REPOSITORY_DISTRIBUTOR_TYPE,
                     distributor_id),
        action_tag('update_distributor')
    ]

    update_request = CallRequest(manager.update_distributor_config,
                                 [repo_id, distributor_id],
                                 {'distributor_config': config},
                                 resources=resources,
                                 tags=tags,
                                 archive=True,
                                 kwarg_blacklist=['distributor_config'])

    call_requests.append(update_request)

    # append unbind itineraries foreach bound consumer

    options = {}
    manager = managers.consumer_bind_manager()
    for bind in manager.find_by_distributor(repo_id, distributor_id):
        bind_requests = bind_itinerary(bind['consumer_id'], bind['repo_id'],
                                       bind['distributor_id'],
                                       bind['notify_agent'],
                                       bind['binding_config'], options)
        if bind_requests:
            bind_requests[0].depends_on(update_request.id)
            call_requests.extend(bind_requests)

    return call_requests
Esempio n. 11
0
    def test_bind_no_notify_agent(self):
        # Setup
        self.populate()

        # Test
        options = {}
        itinerary = bind_itinerary(
            self.CONSUMER_ID,
            self.REPO_ID,
            self.DISTRIBUTOR_ID,
            False,
            self.BINDING_CONFIG,
            options)
        call_reports = self.coordinator.execute_multiple_calls(itinerary)

        # Verify
        self.assertEqual(len(call_reports), 1)
        self.assertEqual(call_reports[0].call_request_tags, self.BIND_TAGS)
        for call in call_reports:
            self.assertNotEqual(call.state, dispatch_constants.CALL_REJECTED_RESPONSE)

        # run task #1 (actual bind)
        self.run_next()

        # verify bind created
        manager = factory.consumer_bind_manager()
        binds = manager.find_by_consumer(self.CONSUMER_ID)
        self.assertEquals(len(binds), 1)
        bind = binds[0]
        self.assertEqual(bind['consumer_id'], self.CONSUMER_ID)
        self.assertEqual(bind['repo_id'], self.REPO_ID)
        self.assertEqual(bind['distributor_id'], self.DISTRIBUTOR_ID)
        self.assertEqual(bind['notify_agent'], False)
        self.assertEqual(bind['binding_config'], self.BINDING_CONFIG)

        # run task #2 (notify consumer)
        try:
            self.run_next()
            self.fail('Second task to bind found')
        except Exception:
            pass  # the agent notify shouldn't trigger

        # verify agent was not notified
        self.assertTrue(not mock_agent.Consumer.bind.called)
Esempio n. 12
0
    def test_bind_no_notify_agent(self):
        # Setup
        self.populate()

        # Test
        options = {}
        itinerary = bind_itinerary(
            self.CONSUMER_ID,
            self.REPO_ID,
            self.DISTRIBUTOR_ID,
            False,
            self.BINDING_CONFIG,
            options)
        call_reports = self.coordinator.execute_multiple_calls(itinerary)

        # Verify
        self.assertEqual(len(call_reports), 1)
        self.assertEqual(call_reports[0].call_request_tags, self.BIND_TAGS)
        for call in call_reports:
            self.assertNotEqual(call.state, dispatch_constants.CALL_REJECTED_RESPONSE)

        # run task #1 (actual bind)
        self.run_next()

        # verify bind created
        manager = factory.consumer_bind_manager()
        binds = manager.find_by_consumer(self.CONSUMER_ID)
        self.assertEquals(len(binds), 1)
        bind = binds[0]
        self.assertEqual(bind['consumer_id'], self.CONSUMER_ID)
        self.assertEqual(bind['repo_id'], self.REPO_ID)
        self.assertEqual(bind['distributor_id'], self.DISTRIBUTOR_ID)
        self.assertEqual(bind['notify_agent'], False)
        self.assertEqual(bind['binding_config'], self.BINDING_CONFIG)

        # run task #2 (notify consumer)
        try:
            self.run_next()
            self.fail('Second task to bind found')
        except Exception:
            pass  # the agent notify shouldn't trigger

        # verify agent was not notified
        self.assertTrue(not mock_agent.Consumer.bind.called)
Esempio n. 13
0
 def POST(self, consumer_id):
     """
     Create a bind association between the specified
     consumer by id included in the URL path and a repo-distributor
     specified in the POST body: {repo_id:<str>, distributor_id:<str>}.
     Designed to be idempotent so only MissingResource is expected to
     be raised by manager.
     @param consumer_id: The consumer to bind.
     @type consumer_id: str
     @return: The list of call_reports
     @rtype: list
     """
     # validate resources
     manager = managers.consumer_manager()
     manager.get_consumer(consumer_id)
     # bind
     body = self.params()
     repo_id = body.get('repo_id')
     distributor_id = body.get('distributor_id')
     options = body.get('options', {})
     call_requests = bind_itinerary(consumer_id, repo_id, distributor_id, options)
     execution.execute_multiple(call_requests)
Esempio n. 14
0
def distributor_update_itinerary(repo_id, distributor_id, config, delta=None):
    """
    Get the itinerary for updating a repository distributor.
      1. Update the distributor on the server.
      2. (re)bind any bound consumers.

    :param repo_id:         A repository ID.
    :type  repo_id:         str
    :param distributor_id:  A unique distributor id
    :type  distributor_id:  str
    :param config:          A configuration dictionary for a distributor instance. The contents of this
                            dict depends on the type of distributor.
    :type  config:          dict
    :param delta:           A dictionary used to change other saved configuration values for a
                            distributor instance. This currently only supports the 'auto_publish'
                            keyword, which should have a value of type bool
    :type  delta:           dict

    :return: A list of call_requests known as an itinerary.
    :rtype: list
    """

    call_requests = []

    # update the distributor

    manager = managers.repo_distributor_manager()

    tags = [
        resource_tag(dispatch_constants.RESOURCE_REPOSITORY_TYPE, repo_id),
        resource_tag(dispatch_constants.RESOURCE_REPOSITORY_DISTRIBUTOR_TYPE, distributor_id),
        action_tag('update_distributor')
    ]

    # Retrieve configuration options from the delta
    auto_publish = None
    if delta is not None:
        auto_publish = delta.get('auto_publish')

    update_request = CallRequest(manager.update_distributor_config, [repo_id, distributor_id],
                                 {'distributor_config': config, 'auto_publish': auto_publish}, tags=tags,
                                 archive=True, kwarg_blacklist=['distributor_config', 'auto_publish'])

    update_request.updates_resource(dispatch_constants.RESOURCE_REPOSITORY_TYPE, repo_id)
    update_request.updates_resource(dispatch_constants.RESOURCE_REPOSITORY_DISTRIBUTOR_TYPE, distributor_id)

    call_requests.append(update_request)

    # append unbind itineraries foreach bound consumer

    options = {}
    manager = managers.consumer_bind_manager()
    for bind in manager.find_by_distributor(repo_id, distributor_id):
        bind_requests = bind_itinerary(
            bind['consumer_id'],
            bind['repo_id'],
            bind['distributor_id'],
            bind['notify_agent'],
            bind['binding_config'],
            options)
        if bind_requests:
            bind_requests[0].depends_on(update_request.id)
            call_requests.extend(bind_requests)

    return call_requests