Beispiel #1
0
def test_parse_env_map():
    a = set_deployment_parser().parse_args(
        ['--env', 'key1=value1', '--env', 'key2=value2'])
    assert a.env == {'key1': 'value1', 'key2': 'value2'}

    a = set_deployment_parser().parse_args(
        ['--env', 'key1=value1', 'key2=value2', 'key3=3'])
    assert a.env == {'key1': 'value1', 'key2': 'value2', 'key3': 3}
Beispiel #2
0
def test_dynamic_polling_overwrite_default_config(polling):
    endpoint_polling = {'/search': PollingType.ANY, '*': polling}
    args = set_deployment_parser().parse_args([
        '--uses',
        'DynamicPollingExecutorDefaultNames',
        '--shards',
        str(2),
        '--polling',
        json.dumps(endpoint_polling),
    ])
    pod = Deployment(args)

    with pod:
        response = GrpcConnectionPool.send_request_sync(
            _create_test_data_message(endpoint='/search'),
            f'{pod.head_args.host}:{pod.head_args.port_in}',
            endpoint='/search',
        )
        assert (len(response.docs) == 1 + 1
                )  # 1 source doc + 1 doc added by the one shard

        response = GrpcConnectionPool.send_request_sync(
            _create_test_data_message(endpoint='/index'),
            f'{pod.head_args.host}:{pod.head_args.port_in}',
            endpoint='/index',
        )
        assert (len(response.docs) == 1 + 1
                )  # 1 source doc + 1 doc added by the one shard
Beispiel #3
0
def test_pod_naming_with_replica():
    args = set_deployment_parser().parse_args(
        ['--name', 'pod', '--replicas', '2'])
    with Deployment(args) as bp:
        assert bp.head_pod.name == 'pod/head'
        assert bp.shards[0]._pods[0].name == 'pod/rep-0'
        assert bp.shards[0]._pods[1].name == 'pod/rep-1'
Beispiel #4
0
def test_use_from_local_hub_deployment_level(test_envs, mocker, monkeypatch,
                                             local_hub_executor):
    from jina.hubble.hubio import HubIO, HubExecutor

    mock = mocker.Mock()

    def _mock_fetch(name, tag=None, secret=None, force=False):
        mock(name=name)
        return (
            HubExecutor(
                uuid='hello',
                name='alias_dummy',
                tag='v0',
                image_name='jinahub/pod.dummy_mwu_encoder',
                md5sum=None,
                visibility=True,
                archive_url=None,
            ),
            False,
        )

    monkeypatch.setattr(HubIO, 'fetch_meta', _mock_fetch)
    a = set_deployment_parser().parse_args(['--uses', 'jinahub://hello'])
    with Deployment(a):
        pass
Beispiel #5
0
async def test_scale_remote_pod_async(
    deployment_params, async_jinad_client, slow_down_tests
):
    num_replicas, scale_to, shards = deployment_params
    args = set_deployment_parser().parse_args(
        ['--replicas', str(num_replicas), '--shards', str(shards)]
    )
    payload = replace_enum_to_str(ArgNamespace.flatten_to_dict(args))

    workspace_id = await async_jinad_client.workspaces.create(
        paths=[os.path.join(cur_dir, cur_dir)]
    )
    success, pod_id = await async_jinad_client.deployments.create(
        workspace_id=workspace_id, payload=payload
    )
    assert success

    resp = await async_jinad_client.deployments.get(pod_id)
    remote_pod_args = resp['arguments']['object']['arguments']
    assert remote_pod_args['replicas'] == num_replicas
    assert remote_pod_args['shards'] == shards

    await async_jinad_client.deployments.scale(id=pod_id, replicas=scale_to)
    resp = await async_jinad_client.deployments.get(pod_id)
    remote_pod_args = resp['arguments']['object']['arguments']
    assert remote_pod_args['replicas'] == scale_to
    assert remote_pod_args['shards'] == shards
    assert await async_jinad_client.deployments.delete(pod_id)
Beispiel #6
0
def test_pod_rolling_update(shards):
    args_list = ['--replicas', '7']
    args_list.extend(['--shards', str(shards)])
    args = set_deployment_parser().parse_args(args_list)
    args.uses = 'AppendParamExecutor'
    args.uses_with = {'param': 10}
    with Deployment(args) as pod:

        async def run_async_test():
            response_texts = await _send_requests(pod)
            assert 2 == len(response_texts)
            assert all(text in response_texts for text in ['10', 'client'])

            await pod.rolling_update(uses_with={'param': 20})
            response_texts = await _send_requests(pod)
            assert 2 == len(response_texts)
            assert all(text in response_texts for text in ['20', 'client'])
            assert '10' not in response_texts

        p = Process(target=run_async_test)
        p.start()
        p.join()
        assert p.exitcode == 0

    Deployment(args).start().close()
Beispiel #7
0
def test_pod_upload_files(
    replicas,
    upload_files,
    uses,
    uses_before,
    uses_after,
    py_modules,
    expected,
):
    args = set_deployment_parser().parse_args([
        '--uses',
        uses,
        '--uses-before',
        uses_before,
        '--uses-after',
        uses_after,
        '--py-modules',
        *py_modules,
        '--upload-files',
        *upload_files,
        '--replicas',
        str(replicas),
    ])
    pod = Deployment(args)
    for k, v in pod.pod_args.items():
        if k in ['head', 'tail']:
            if v:
                pass
                # assert sorted(v.upload_files) == sorted(expected)
        elif v is not None and k == 'pods':
            for shard_id in v:
                for pod in v[shard_id]:
                    print(sorted(pod.upload_files))
                    print(sorted(expected))
                    assert sorted(pod.upload_files) == sorted(expected)
Beispiel #8
0
def external_deployment_args():
    args = ['--port-in', str(45678)]
    args = vars(set_deployment_parser().parse_args(args))
    del args['external']
    del args['deployment_role']
    del args['host']
    return args
Beispiel #9
0
def _create_regular_deployment(
    port,
    name='',
    executor=None,
    uses_before=False,
    uses_after=False,
    polling=PollingType.ANY,
    shards=None,
    replicas=None,
):
    args = set_deployment_parser().parse_args([])
    args.port = port
    args.name = name
    if shards:
        args.shards = shards
    if replicas:
        args.replicas = replicas
    args.polling = polling
    if executor:
        args.uses = executor if executor else 'NameChangeExecutor'
    if uses_after:
        args.uses_after = executor if executor else 'NameChangeExecutor'
    if uses_before:
        args.uses_before = executor if executor else 'NameChangeExecutor'
    return Deployment(args)
Beispiel #10
0
def test_pod_context_replicas(replicas):
    args_list = ['--replicas', str(replicas)]
    args = set_deployment_parser().parse_args(args_list)
    with Deployment(args) as bp:
        assert bp.num_pods == replicas

    Deployment(args).start().close()
Beispiel #11
0
def test_dynamic_polling_default_config(polling):
    args = set_deployment_parser().parse_args([
        '--uses',
        'DynamicPollingExecutorDefaultNames',
        '--shards',
        str(2),
        '--polling',
        polling,
    ])
    pod = Deployment(args)

    with pod:
        response = GrpcConnectionPool.send_request_sync(
            _create_test_data_message(endpoint='/search'),
            f'{pod.head_args.host}:{pod.head_args.port_in}',
            endpoint='/search',
        )
        assert len(response.docs) == 1 + 2

        response = GrpcConnectionPool.send_request_sync(
            _create_test_data_message(endpoint='/index'),
            f'{pod.head_args.host}:{pod.head_args.port_in}',
            endpoint='/index',
        )
        assert len(response.docs) == 1 + 1
Beispiel #12
0
def test_pod_context_shards_replicas(shards):
    args_list = ['--replicas', str(3)]
    args_list.extend(['--shards', str(shards)])
    args = set_deployment_parser().parse_args(args_list)
    with Deployment(args) as bp:
        assert bp.num_pods == shards * 3 + 1

    Deployment(args).start().close()
Beispiel #13
0
def pod_args():
    args = [
        '--name',
        'test',
        '--replicas',
        '2',
        '--host',
        __default_host__,
    ]
    return set_deployment_parser().parse_args(args)
Beispiel #14
0
async def _create(deployment: 'DeploymentModel', envs: Optional[Dict] = {}):
    """

    .. #noqa: DAR101
    .. #noqa: DAR201"""
    try:
        args = ArgNamespace.kwargs2namespace(deployment.dict(),
                                             set_deployment_parser())
        return store.add(args, envs)
    except Exception as ex:
        raise PartialDaemon400Exception from ex
Beispiel #15
0
def pod_args_singleton():
    args = [
        '--name',
        'test2',
        '--uses-before',
        __default_executor__,
        '--replicas',
        '1',
        '--host',
        __default_host__,
    ]
    return set_deployment_parser().parse_args(args)
Beispiel #16
0
def test_pod_args_remove_uses_ba():
    args = set_deployment_parser().parse_args([])
    with Deployment(args) as p:
        assert p.num_pods == 2

    args = set_deployment_parser().parse_args([
        '--uses-before', __default_executor__, '--uses-after',
        __default_executor__
    ])
    with Deployment(args) as p:
        assert p.num_pods == 2

    args = set_deployment_parser().parse_args([
        '--uses-before',
        __default_executor__,
        '--uses-after',
        __default_executor__,
        '--replicas',
        '2',
    ])
    with Deployment(args) as p:
        assert p.num_pods == 3
Beispiel #17
0
def external_deployment_pre_shards_args(num_shards):
    args = [
        '--uses',
        'MyExternalExecutor',
        '--name',
        'external_real',
        '--port',
        str(random_port()),
        '--shards',
        str(num_shards),
        '--polling',
        'all',
    ]
    return set_deployment_parser().parse_args(args)
Beispiel #18
0
    def dump(self, data: 'Flow') -> Dict:
        """
        :param data: versioned flow object
        :return: the dictionary given a versioned flow object
        """
        r = {}
        if data._version:
            r['version'] = data._version

        # to maintain order - version -> with -> executors
        r['with'] = {}
        if data._kwargs:
            r['with'].update(data._kwargs)

        if data._common_kwargs:
            r['with'].update(data._common_kwargs)

        if data._deployment_nodes:
            r['executors'] = []

        last_name = 'gateway'
        for k, v in data._deployment_nodes.items():
            kwargs = {}
            # only add "needs" when the value is not the last deployment name
            if list(v.needs) != [last_name]:
                kwargs = {'needs': list(v.needs)}

            # get nondefault kwargs
            parser = set_deployment_parser()
            if v.role == DeploymentRoleType.GATEWAY:
                parser = set_gateway_parser()

            non_default_kw = ArgNamespace.get_non_defaults_args(v.args, parser)

            kwargs.update(non_default_kw)

            for t in _get_taboo(parser):
                if t in kwargs:
                    kwargs.pop(t)
            if k == 'gateway':
                if 'JINA_FULL_CLI' in os.environ:
                    r['with'].update(kwargs)
                else:
                    continue
            else:
                last_name = kwargs['name']
                r['executors'].append(kwargs)

        return r
Beispiel #19
0
async def test_flow_with_external_native_deployment(logger, docker_images,
                                                    tmpdir):
    class DocReplaceExecutor(Executor):
        @requests
        def add(self, **kwargs):
            return DocumentArray(
                [Document(text='executor was here') for _ in range(100)])

    args = set_deployment_parser().parse_args(['--uses', 'DocReplaceExecutor'])
    with Deployment(args) as external_deployment:
        ports = [args.port for args in external_deployment.pod_args['pods'][0]]
        flow = Flow(name='k8s_flow-with_external_deployment', port=9090).add(
            name='external_executor',
            external=True,
            host=f'172.17.0.1',
            port=ports[0],
        )

        namespace = 'test-flow-with-external-deployment'
        dump_path = os.path.join(str(tmpdir), namespace)
        flow.to_k8s_yaml(dump_path, k8s_namespace=namespace)

        from kubernetes import client

        api_client = client.ApiClient()
        core_client = client.CoreV1Api(api_client=api_client)
        app_client = client.AppsV1Api(api_client=api_client)
        await create_all_flow_deployments_and_wait_ready(
            dump_path,
            namespace=namespace,
            api_client=api_client,
            app_client=app_client,
            core_client=core_client,
            deployment_replicas_expected={
                'gateway': 1,
            },
            logger=logger,
        )
        resp = await run_test(
            flow=flow,
            namespace=namespace,
            core_client=core_client,
            endpoint='/',
        )
    docs = resp[0].docs
    assert len(docs) == 100
    for doc in docs:
        assert doc.text == 'executor was here'
    core_client.delete_namespace(namespace)
Beispiel #20
0
def test_worker_services(name: str, shards: str):
    args = set_deployment_parser().parse_args(
        ['--name', name, '--shards', shards])
    deployment_config = DockerComposeConfig(args)

    actual_services = deployment_config.worker_services

    assert len(actual_services) == int(shards)
    for i, deploy in enumerate(actual_services):
        if int(shards) > 1:
            assert deploy.name == f'{name}-{i}'
        else:
            assert deploy.name == name
        assert deploy.jina_deployment_name == name
        assert deploy.shard_id == i
def test_deployments(name: str, shards: str, k8s_connection_pool_call):
    args = set_deployment_parser().parse_args(['--name', name, '--shards', shards])
    deployment_config = K8sDeploymentConfig(args, 'ns', k8s_connection_pool_call)

    actual_deployments = deployment_config.worker_deployments

    assert len(actual_deployments) == int(shards)
    for i, deploy in enumerate(actual_deployments):
        if int(shards) > 1:
            assert deploy.name == f'{name}-{i}'
        else:
            assert deploy.name == name
        assert deploy.jina_deployment_name == name
        assert deploy.shard_id == i
        assert deploy.k8s_connection_pool is k8s_connection_pool_call
Beispiel #22
0
async def _create_external_deployment(api_client, app_client, docker_images,
                                      tmpdir):
    namespace = 'external-deployment-ns'
    args = set_deployment_parser().parse_args([
        '--uses', f'docker://{docker_images[0]}', '--name',
        'external-deployment'
    ])
    external_deployment_config = K8sDeploymentConfig(args=args,
                                                     k8s_namespace=namespace)
    configs = external_deployment_config.to_k8s_yaml()
    deployment_base = os.path.join(tmpdir, 'external-deployment')
    filenames = []
    for name, k8s_objects in configs:
        filename = os.path.join(deployment_base, f'{name}.yml')
        os.makedirs(deployment_base, exist_ok=True)
        with open(filename, 'w+') as fp:
            filenames.append(filename)
            for i, k8s_object in enumerate(k8s_objects):
                yaml.dump(k8s_object, fp)
                if i < len(k8s_objects) - 1:
                    fp.write('---\n')
    from kubernetes import utils

    namespace_object = {
        'apiVersion': 'v1',
        'kind': 'Namespace',
        'metadata': {
            'name': f'{namespace}'
        },
    }
    try:
        utils.create_from_dict(api_client, namespace_object)
    except:
        pass

    for filename in filenames:
        try:
            utils.create_from_yaml(
                api_client,
                yaml_file=filename,
                namespace=namespace,
            )
        except:
            pass

    await asyncio.sleep(1.0)
Beispiel #23
0
def test_pod_remote_pod_replicas_host(num_shards, num_replicas):
    args = set_deployment_parser().parse_args([
        '--shards',
        str(num_shards),
        '--replicas',
        str(num_replicas),
        '--host',
        __default_host__,
    ])
    assert args.host == __default_host__
    with Deployment(args) as pod:
        assert pod.num_pods == num_shards * num_replicas + 1
        pod_args = dict(pod.pod_args['pods'])
        for k, replica_args in pod_args.items():
            assert len(replica_args) == num_replicas
            for replica_arg in replica_args:
                assert replica_arg.host == __default_host__
Beispiel #24
0
def test_dynamic_polling_with_config(polling):
    endpoint_polling = {
        '/any': PollingType.ANY,
        '/all': PollingType.ALL,
        '*': polling
    }

    args = set_deployment_parser().parse_args([
        '--uses',
        'DynamicPollingExecutor',
        '--shards',
        str(2),
        '--polling',
        json.dumps(endpoint_polling),
    ])
    pod = Deployment(args)

    with pod:
        response = GrpcConnectionPool.send_request_sync(
            _create_test_data_message(endpoint='/all'),
            f'{pod.head_args.host}:{pod.head_args.port_in}',
            endpoint='/all',
        )
        assert len(response.docs
                   ) == 1 + 2  # 1 source doc + 2 docs added by each shard

        response = GrpcConnectionPool.send_request_sync(
            _create_test_data_message(endpoint='/any'),
            f'{pod.head_args.host}:{pod.head_args.port_in}',
            endpoint='/any',
        )
        assert (len(response.docs) == 1 + 1
                )  # 1 source doc + 1 doc added by the one shard

        response = GrpcConnectionPool.send_request_sync(
            _create_test_data_message(endpoint='/no_polling'),
            f'{pod.head_args.host}:{pod.head_args.port_in}',
            endpoint='/no_polling',
        )
        if polling == 'any':
            assert (len(response.docs) == 1 + 1
                    )  # 1 source doc + 1 doc added by the one shard
        else:
            assert (len(response.docs) == 1 + 2
                    )  # 1 source doc + 1 doc added by the two shards
Beispiel #25
0
def test_pod_activates_replicas():
    args_list = ['--replicas', '3', '--shards', '2', '--disable-reduce']
    args = set_deployment_parser().parse_args(args_list)
    args.uses = 'AppendNameExecutor'
    with Deployment(args) as pod:
        assert pod.num_pods == 7
        response_texts = set()
        # replicas are used in a round robin fashion, so sending 3 requests should hit each one time
        for _ in range(6):
            response = GrpcConnectionPool.send_request_sync(
                _create_test_data_message(),
                f'{pod.head_args.host}:{pod.head_args.port}',
            )
            response_texts.update(response.response.docs.texts)
        assert 4 == len(response_texts)
        assert all(text in response_texts for text in ['0', '1', '2', 'client'])

    Deployment(args).start().close()
Beispiel #26
0
def external_deployment_args(num_replicas, num_shards):
    args = [
        '--uses',
        'MyExternalExecutor',
        '--name',
        'external_real',
        '--port-in',
        str(random_port()),
        '--host-in',
        '0.0.0.0',
        '--shards',
        str(num_shards),
        '--replicas',
        str(num_replicas),
        '--polling',
        'all',
    ]
    return set_deployment_parser().parse_args(args)
Beispiel #27
0
def test_pod_naming_with_shards():
    args = set_deployment_parser().parse_args([
        '--name',
        'pod',
        '--shards',
        '2',
        '--replicas',
        '3',
    ])
    with Deployment(args) as pod:
        assert pod.head_pod.name == 'pod/head'

        assert pod.shards[0].args[0].name == 'pod/shard-0/rep-0'
        assert pod.shards[0].args[1].name == 'pod/shard-0/rep-1'
        assert pod.shards[0].args[2].name == 'pod/shard-0/rep-2'

        assert pod.shards[1].args[0].name == 'pod/shard-1/rep-0'
        assert pod.shards[1].args[1].name == 'pod/shard-1/rep-1'
        assert pod.shards[1].args[2].name == 'pod/shard-1/rep-2'
Beispiel #28
0
def test_deployments(name: str, shards: str, gpus):
    args = set_deployment_parser().parse_args(
        ['--name', name, '--shards', shards, '--gpus', gpus]
    )
    deployment_config = K8sDeploymentConfig(args, 'ns')

    if name != 'gateway' and int(shards) > int(1):
        head_deployment = deployment_config.head_deployment
        assert head_deployment.deployment_args.gpus is None

    actual_deployments = deployment_config.worker_deployments

    assert len(actual_deployments) == int(shards)
    for i, deploy in enumerate(actual_deployments):
        assert deploy.deployment_args.gpus == gpus
        if int(shards) > 1:
            assert deploy.name == f'{name}-{i}'
        else:
            assert deploy.name == name
        assert deploy.jina_deployment_name == name
        assert deploy.shard_id == i
Beispiel #29
0
def test_pod_activates_shards():
    args_list = ['--replicas', '3']
    args_list.extend(['--shards', '3'])
    args = set_deployment_parser().parse_args(args_list)
    args.uses = 'AppendShardExecutor'
    args.polling = PollingType.ALL
    with Deployment(args) as pod:
        assert pod.num_pods == 3 * 3 + 1
        response_texts = set()
        # replicas are used in a round robin fashion, so sending 3 requests should hit each one time
        response = GrpcConnectionPool.send_request_sync(
            _create_test_data_message(),
            f'{pod.head_args.host}:{pod.head_args.port_in}',
        )
        response_texts.update(response.response.docs.texts)
        assert 4 == len(response.response.docs.texts)
        assert 4 == len(response_texts)
        assert all(text in response_texts
                   for text in ['0', '1', '2', 'client'])

    Deployment(args).start().close()
Beispiel #30
0
def test_use_from_local_dir_deployment_level():
    a = set_deployment_parser().parse_args(['--uses', 'dummyhub/config.yml'])
    with Deployment(a):
        pass