Esempio n. 1
0
def nimbus_check_kinto_push_queue():
    """
    Because kinto has a restriction that it can only have a single pending review, this
    task brokers the queue of all experiments ready to be pushed to kinto and ensures
    that only a single experiment is ever in review.

    A scheduled task that
    - Checks the kinto collection for a single rejected experiment from a previous push
      - If one exists, pull it out of the collection and mark it as rejected
    - Checks if there is still a pending review and if so, aborts
    - Gets the list of all experiments ready to be pushed to kinto and pushes the first
      one
    """
    metrics.incr("check_kinto_push_queue.started")

    for application, collection in NimbusExperiment.KINTO_APPLICATION_COLLECTION.items(
    ):
        kinto_client = KintoClient(collection)

        rejected_collection_data = kinto_client.get_rejected_collection_data()
        if rejected_collection_data:
            rejected_slug = kinto_client.get_rejected_record()
            experiment = NimbusExperiment.objects.get(slug=rejected_slug)
            experiment.status = NimbusExperiment.Status.DRAFT
            experiment.save()

            generate_nimbus_changelog(
                experiment,
                get_kinto_user(),
                message=
                f'Rejected: {rejected_collection_data["last_reviewer_comment"]}',
            )

            kinto_client.rollback_changes()

        if kinto_client.has_pending_review():
            metrics.incr(f"check_kinto_push_queue.{collection}_pending_review")
            return

        queued_experiments = NimbusExperiment.objects.filter(
            status=NimbusExperiment.Status.REVIEW, application=application)
        if queued_experiments.exists():
            nimbus_push_experiment_to_kinto.delay(
                queued_experiments.first().id)
            metrics.incr(
                f"check_kinto_push_queue.{collection}_queued_experiment_selected"
            )
        else:
            metrics.incr(
                f"check_kinto_push_queue.{collection}_no_experiments_queued")

    metrics.incr("check_kinto_push_queue.completed")
Esempio n. 2
0
class TestKintoClient(MockKintoClientMixin, TestCase):
    def setUp(self):
        super().setUp()
        self.collection = "test-collection"
        self.client = KintoClient(self.collection)

    @parameterized.expand([
        [False, KINTO_SIGN_STATUS],
        [True, KINTO_REVIEW_STATUS],
    ])
    def test_create_record_creates_record_patches_collection(
            self, review, status):
        client = KintoClient(self.collection, review=review)
        client.create_record({"test": "data"})

        self.mock_kinto_client_creator.assert_called_with(
            server_url=settings.KINTO_HOST,
            auth=(settings.KINTO_USER, settings.KINTO_PASS),
        )

        self.mock_kinto_client.create_record.assert_called_with(
            data={"test": "data"},
            collection=self.collection,
            bucket=settings.KINTO_BUCKET_WORKSPACE,
            if_not_exists=True,
        )

        self.mock_kinto_client.patch_collection.assert_called_with(
            id=self.collection,
            data={"status": status},
            bucket=settings.KINTO_BUCKET_WORKSPACE,
        )

    @parameterized.expand([
        [False, KINTO_SIGN_STATUS],
        [True, KINTO_REVIEW_STATUS],
    ])
    def test_update_record_updates_record_patches_collection(
            self, review, status):
        client = KintoClient(self.collection, review=review)

        data = {"id": "my-record", "field": "value"}
        client.update_record(data)

        self.mock_kinto_client.update_record.assert_called_with(
            data=data,
            collection=self.collection,
            bucket=settings.KINTO_BUCKET_WORKSPACE,
            if_match='"0"',
        )

        self.mock_kinto_client.patch_collection.assert_called_with(
            id=self.collection,
            data={"status": status},
            bucket=settings.KINTO_BUCKET_WORKSPACE,
        )

    @parameterized.expand([
        [False, KINTO_SIGN_STATUS],
        [True, KINTO_REVIEW_STATUS],
    ])
    def test_delete_record_deletes_record_patches_collection(
            self, review, status):
        client = KintoClient(self.collection, review=review)

        record_id = "abc-123"
        client.delete_record(record_id)

        self.mock_kinto_client_creator.assert_called_with(
            server_url=settings.KINTO_HOST,
            auth=(settings.KINTO_USER, settings.KINTO_PASS),
        )

        self.mock_kinto_client.delete_record.assert_called_with(
            id=record_id,
            collection=self.collection,
            bucket=settings.KINTO_BUCKET_WORKSPACE,
        )

        self.mock_kinto_client.patch_collection.assert_called_with(
            id=self.collection,
            data={"status": status},
            bucket=settings.KINTO_BUCKET_WORKSPACE,
        )

    def test_rollback_changes_patches_collection(self):
        self.client.rollback_changes()

        self.mock_kinto_client_creator.assert_called_with(
            server_url=settings.KINTO_HOST,
            auth=(settings.KINTO_USER, settings.KINTO_PASS),
        )

        self.mock_kinto_client.patch_collection.assert_called_with(
            id=self.collection,
            data={"status": KINTO_ROLLBACK_STATUS},
            bucket=settings.KINTO_BUCKET_WORKSPACE,
        )

    def test_returns_true_for_pending_review(self):
        self.setup_kinto_pending_review()
        self.assertTrue(self.client.has_pending_review())

    def test_returns_false_for_no_pending_review(self):
        self.setup_kinto_no_pending_review()
        self.assertFalse(self.client.has_pending_review())

    def test_returns_records(self):
        slug = "test-slug"
        self.setup_kinto_get_main_records([slug])
        self.assertEqual(self.client.get_main_records(),
                         {slug: {
                             "id": slug,
                             "last_modified": "0"
                         }})

    def test_returns_no_records(self):
        self.setup_kinto_get_main_records([])
        self.assertEqual(self.client.get_main_records(), {})

    def test_returns_nothing_when_not_rejects(self):
        self.setup_kinto_no_pending_review()
        self.assertIsNone(self.client.get_rejected_collection_data())

    def test_returns_rejected_data(self):
        self.setup_kinto_rejected_review()
        self.assertTrue(self.client.get_rejected_collection_data())
Esempio n. 3
0
class TestKintoClient(MockKintoClientMixin, TestCase):
    def setUp(self):
        super().setUp()
        self.collection = "test-collection"
        self.client = KintoClient(self.collection)

    def test_push_to_kinto_sends_data_updates_collection(self):
        self.client.push_to_kinto({"test": "data"})

        self.mock_kinto_client_creator.assert_called_with(
            server_url=settings.KINTO_HOST,
            auth=(settings.KINTO_USER, settings.KINTO_PASS),
        )

        self.mock_kinto_client.create_record.assert_called_with(
            data={"test": "data"},
            collection=self.collection,
            bucket=settings.KINTO_BUCKET,
            if_not_exists=True,
        )

        self.mock_kinto_client.patch_collection.assert_called_with(
            id=self.collection,
            data={"status": KINTO_REVIEW_STATUS},
            bucket=settings.KINTO_BUCKET,
        )

    def test_rollback_changes_patches_collection(self):
        self.client.rollback_changes()

        self.mock_kinto_client_creator.assert_called_with(
            server_url=settings.KINTO_HOST,
            auth=(settings.KINTO_USER, settings.KINTO_PASS),
        )

        self.mock_kinto_client.patch_collection.assert_called_with(
            id=self.collection,
            data={"status": KINTO_ROLLBACK_STATUS},
            bucket=settings.KINTO_BUCKET,
        )

    def test_returns_true_for_pending_review(self):
        self.setup_kinto_pending_review()
        self.assertTrue(self.client.has_pending_review())

    def test_returns_false_for_no_pending_review(self):
        self.setup_kinto_no_pending_review()
        self.assertFalse(self.client.has_pending_review())

    def test_returns_records(self):
        slug = "test-slug"
        self.setup_kinto_get_main_records([slug])
        self.assertEqual(self.client.get_main_records(), [{"id": slug}])

    def test_returns_no_records(self):
        self.setup_kinto_get_main_records([])
        self.assertEqual(self.client.get_main_records(), [])

    def test_returns_nothing_when_not_rejects(self):
        self.setup_kinto_no_pending_review()
        self.assertIsNone(self.client.get_rejected_collection_data())

    def test_returns_rejected_data(self):
        self.setup_kinto_rejected_review()
        self.assertTrue(self.client.get_rejected_collection_data())

    def test_returns_rejected_record(self):
        self.mock_kinto_client.get_records.side_effect = [
            [{
                "id": "bug-12345-rapid-test-release-55"
            }],
            [
                {
                    "id": "bug-12345-rapid-test-release-55"
                },
                {
                    "id": "bug-9999-rapid-test-release-55"
                },
            ],
        ]
        self.assertEqual(self.client.get_rejected_record(),
                         "bug-9999-rapid-test-release-55")