Example #1
0
    def test_list(self, batch_p, get_p):
        batch_p.return_value = V1JobList(
            items=[V1Pod(metadata=V1ObjectMeta(name='drwho-cate-sdav'))])
        get_p.return_value = {
            'cubegen_id': 'id',
            'status': 'Ready',
            'output': ['bla'],
            'progress': 100
        }
        res = cubegens.list('drwho')

        self.assertEqual(1, len(res))
        self.assertDictEqual(
            {
                'cubegen_id': 'id',
                'status': 'Ready',
                'output': ['bla'],
                'progress': 100
            }, res[0])

        batch_p.side_effect = ApiException(401, 'Unauthorized')

        with self.assertRaises(api.ApiError) as e:
            cubegens.list(user_id='drwho')

        self.assertIn("Reason: Unauthorized", str(e.exception))
        self.assertIn("401", str(e.exception))
        self.assertEqual(400, e.exception.status_code)
Example #2
0
    def test_fetch_jobs_continue(self, mock_batch_client):
        _continue = "xyz"
        mock_batch_client.list_namespaced_job.side_effect = [
            V1JobList(
                items=[V1Job(metadata=V1ObjectMeta(name="1"))],
                metadata=V1ListMeta(_continue=_continue),
            ),
            V1JobList(
                items=[V1Job(metadata=V1ObjectMeta(name="2"))], metadata=V1ListMeta()
            ),
        ]
        namespace = "blech"
        manager = JobManager(
            namespace=namespace, signer=Mock(), register=StaticJobDefinitionsRegister()
        )

        assert len(list(manager.fetch_jobs())) == 2
        assert mock_batch_client.list_namespaced_job.call_count == 2
        mock_batch_client.list_namespaced_job.assert_called_with(
            namespace=namespace, _continue=_continue
        )
Example #3
0
    def test_fetch_jobs_filters(self, mock_batch_client):
        mock_batch_client.list_namespaced_job.return_value = V1JobList(
            items=[V1Job(metadata=V1ObjectMeta(name="1"))], metadata=V1ListMeta()
        )
        namespace = "hellomoto"
        signer = JobSigner("foo")
        manager = JobManager(
            namespace=namespace, signer=signer, register=StaticJobDefinitionsRegister()
        )

        assert len(list(manager.fetch_jobs(extra="filter"))) == 1
        mock_batch_client.list_namespaced_job.assert_called_once_with(
            namespace=namespace, label_selector=signer.label_selector(extra="filter")
        )
Example #4
0
    def test_fetch_jobs_job_definition_name(self, mock_batch_client):
        namespace = "phd"
        signer = JobSigner("school")
        manager = JobManager(
            namespace=namespace, signer=signer, register=StaticJobDefinitionsRegister()
        )
        job_definition_name = "jd"
        mock_batch_client.list_namespaced_job.return_value = V1JobList(
            items=[], metadata=V1ListMeta()
        )

        list(manager.fetch_jobs(job_definition_name))

        mock_batch_client.list_namespaced_job.assert_called_once_with(
            namespace=namespace,
            label_selector=signer.label_selector(job_definition_name),
        )
Example #5
0
    def test_logs(self, pod_read_p, pod_p):
        pod_p.return_value = V1JobList(
            items=[V1Pod(metadata=V1ObjectMeta(name='drwho-cate-sdav'))])
        pod_read_p.return_value = 'bla'

        res = cubegens.logs('drwho')

        self.assertEqual(1, len(res))
        self.assertEqual([
            'bla',
        ], res)

        pod_p.side_effect = ApiException(401, 'Unauthorized')

        with self.assertRaises(api.ApiError) as e:
            cubegens.logs('drwho', raises=True)

        self.assertIn("Reason: Unauthorized", str(e.exception))
        self.assertIn("401", str(e.exception))
        self.assertEqual(400, e.exception.status_code)
def test_delete_complete_jobs_raises_server_error(api: MagicMock,
                                                  batch_api: MagicMock):
    batch_api.list_namespaced_job.return_value = V1JobList(items=[
        # delete because complete
        V1Job(
            metadata=V1ObjectMeta(
                name="flush-pv-1", uid="uid-flush-pv-1", resource_version="1"),
            status=V1JobStatus(
                conditions=[V1JobCondition(status="", type="Complete")]),
        ),
    ])

    def delete_job(name, namespace, body):
        raise ApiException(reason="Server Error")

    batch_api.delete_namespaced_job.side_effect = delete_job

    with pytest.raises(ApiException):
        delete_complete_jobs(api, batch_api, "namespace")

    batch_api.list_namespaced_job.called_once_with("namespace")
Example #7
0
def test_flush_released_pvs(api: MagicMock, batch_api: MagicMock):
    api.list_persistent_volume.return_value = V1PersistentVolumeList(
        items=[
            # don't flush because job exists
            V1PersistentVolume(metadata=V1ObjectMeta(name="pv-0")),
            # don't flush because wrong namespace
            V1PersistentVolume(
                metadata=V1ObjectMeta(name="pv-4"),
                spec=V1PersistentVolumeSpec(
                    claim_ref=V1ObjectReference(namespace="other"),
                    persistent_volume_reclaim_policy="Retain",
                ),
                status=V1PersistentVolumeStatus(phase="Released"),
            ),
            # don't flush because it's already done
            V1PersistentVolume(
                metadata=V1ObjectMeta(name="pv-5"),
                spec=V1PersistentVolumeSpec(
                    claim_ref=V1ObjectReference(namespace="namespace"),
                    persistent_volume_reclaim_policy="Delete",
                ),
                status=V1PersistentVolumeStatus(phase="Released"),
            ),
            # don't flush because it's in use
            V1PersistentVolume(
                metadata=V1ObjectMeta(name="pv-6"),
                spec=V1PersistentVolumeSpec(
                    claim_ref=V1ObjectReference(
                        name="queue-web-0", namespace="namespace"
                    ),
                    persistent_volume_reclaim_policy="Retain",
                ),
                status=V1PersistentVolumeStatus(phase="Bound"),
            ),
            # try to flush because pvc is bound but job was created after jobs were listed
            V1PersistentVolume(
                metadata=V1ObjectMeta(name="pv-7"),
                spec=V1PersistentVolumeSpec(
                    claim_ref=V1ObjectReference(
                        name="flush-pv-7", namespace="namespace"
                    ),
                    persistent_volume_reclaim_policy="Retain",
                ),
                status=V1PersistentVolumeStatus(phase="Bound"),
            ),
            # flush because pvc is bound but job does not exist
            V1PersistentVolume(
                metadata=V1ObjectMeta(name="pv-8"),
                spec=V1PersistentVolumeSpec(
                    claim_ref=V1ObjectReference(
                        name="flush-pv-8", namespace="namespace"
                    ),
                    persistent_volume_reclaim_policy="Retain",
                ),
                status=V1PersistentVolumeStatus(phase="Bound"),
            ),
            # flush because pvc is not yet bound and job does not exist
            V1PersistentVolume(
                metadata=V1ObjectMeta(name="pv-9"),
                spec=V1PersistentVolumeSpec(
                    claim_ref=V1ObjectReference(
                        name="queue-web-0", namespace="namespace"
                    ),
                    persistent_volume_reclaim_policy="Retain",
                ),
                status=V1PersistentVolumeStatus(phase="Released"),
            ),
            # flush because pvc and job both do not exist
            V1PersistentVolume(
                metadata=V1ObjectMeta(name="pv-A"),
                spec=V1PersistentVolumeSpec(
                    claim_ref=V1ObjectReference(
                        name="queue-web-0", namespace="namespace"
                    ),
                    persistent_volume_reclaim_policy="Retain",
                ),
                status=V1PersistentVolumeStatus(phase="Released"),
            ),
        ]
    )

    def create_pvc(namespace: str, body: V1PersistentVolumeClaim):
        if body.metadata.name == "flush-pv-9":
            exc = ApiException(status=409, reason="Conflict")
            exc.body = '{"reason":"AlreadyExists"}'
            raise exc
        body.metadata.uid = "uid-" + body.metadata.name
        body.metadata.resource_version = "1"
        return body

    api.create_namespaced_persistent_volume_claim.side_effect = create_pvc

    def read_pvc(name: str, namespace: str):
        return V1PersistentVolumeClaim(
            metadata=V1ObjectMeta(
                name=name, namespace=namespace, uid="uid-" + name, resource_version="2"
            )
        )

    api.read_namespaced_persistent_volume_claim.side_effect = read_pvc

    batch_api.list_namespaced_job.return_value = V1JobList(
        items=[V1Job(metadata=V1ObjectMeta(name="flush-pv-0"))]
    )

    def create_job(namespace, body):
        if body.metadata.name == "flush-pv-7":
            exc = ApiException(status=409, reason="Conflict")
            exc.body = '{"reason":"AlreadyExists"}'
            raise exc

    batch_api.create_namespaced_job.side_effect = create_job

    flush_released_pvs(api, batch_api, "command", "env", "image", "namespace")

    api.list_persistent_volume.assert_called_once_with()
    batch_api.list_namespaced_job.assert_called_once_with("namespace")
    assert [f"flush-pv-{i}" for i in "9A"] == [
        call.kwargs["body"].metadata.name
        for call in api.create_namespaced_persistent_volume_claim.call_args_list
    ]
    api.read_namespaced_persistent_volume_claim.assert_called_once_with(
        "flush-pv-9", "namespace"
    )
    assert [("pv-9", "flush-pv-9"), ("pv-A", "flush-pv-A"),] == [
        (
            call.kwargs["name"],
            call.kwargs["body"].spec.claim_ref
            and call.kwargs["body"].spec.claim_ref.name,
        )
        for call in api.patch_persistent_volume.call_args_list
    ]
    assert [f"flush-pv-{i}" for i in "789A"] == [
        call.kwargs["body"].metadata.name
        for call in batch_api.create_namespaced_job.call_args_list
    ]
    batch_api.read_namespaced_job.assert_called_once_with("flush-pv-7", "namespace")
def test_delete_complete_jobs(api: MagicMock, batch_api: MagicMock):
    batch_api.list_namespaced_job.return_value = V1JobList(items=[
        # delete because complete
        *(V1Job(
            metadata=V1ObjectMeta(
                name=f"flush-pv-{i}",
                uid=f"uid-flush-pv-{i}",
                resource_version=f"{i}",
            ),
            status=V1JobStatus(
                conditions=[V1JobCondition(status="", type="Complete")]),
        ) for i in range(3)),
        # don't delete because already deleted
        V1Job(
            metadata=V1ObjectMeta(
                name="flush-pv-3",
                deletion_timestamp=datetime.utcnow(),
            ),
            status=V1JobStatus(
                conditions=[V1JobCondition(status="", type="Complete")]),
        ),
        # don't delete because not complete
        V1Job(
            metadata=V1ObjectMeta(name="flush-pv-4"),
            status=V1JobStatus(
                conditions=[V1JobCondition(status="", type="Pending")]),
        ),
        # don't delete because status does not contain conditions
        V1Job(metadata=V1ObjectMeta(name="flush-pv-5"), status=V1JobStatus()),
        # don't delete because not a flush job
        V1Job(
            metadata=V1ObjectMeta(name="cron-1"),
            status=V1JobStatus(
                conditions=[V1JobCondition(status="", type="Complete")]),
        ),
    ])

    def delete_job(name, namespace, body):
        if name == "flush-pv-1":
            raise ApiException(reason="Conflict")
        if name == "flush-pv-2":
            raise ApiException(reason="Not Found")

    batch_api.delete_namespaced_job.side_effect = delete_job

    delete_complete_jobs(api, batch_api, "namespace")

    batch_api.list_namespaced_job.assert_called_once_with("namespace")
    assert [(f"pv-{i}", "Delete") for i in range(3)] == [(
        call.kwargs["name"],
        call.kwargs["body"].spec.persistent_volume_reclaim_policy,
    ) for call in api.patch_persistent_volume.call_args_list]
    assert [(f"flush-pv-{i}", "namespace", [
        ("Job", f"flush-pv-{i}")
    ]) for i in range(3)] == [(
        call.kwargs["name"],
        call.kwargs["namespace"],
        [(ref.kind, ref.name)
         for ref in call.kwargs["body"].metadata.owner_references],
    ) for call in api.patch_namespaced_persistent_volume_claim.call_args_list]
    assert [(f"flush-pv-{i}", "namespace", f"uid-flush-pv-{i}", f"{i}")
            for i in range(3)] == [(
                call.kwargs["name"],
                call.kwargs["namespace"],
                call.kwargs["body"].preconditions.uid,
                call.kwargs["body"].preconditions.resource_version,
            ) for call in batch_api.delete_namespaced_job.call_args_list]