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
def get_gateway_yamls( self, ) -> List[Dict]: import os image_name = os.getenv( 'JINA_GATEWAY_IMAGE', f'jinaai/jina:{self.version}-py38-standard' ) cargs = copy.copy(self.deployment_args) cargs.deployments_addresses = self.k8s_deployments_addresses from jina.helper import ArgNamespace from jina.parsers import set_gateway_parser taboo = { 'uses_with', 'uses_metas', 'volumes', 'uses_before', 'uses_after', 'workspace', 'workspace_id', 'upload_files', 'noblock_on_start', 'env', } non_defaults = ArgNamespace.get_non_defaults_args( cargs, set_gateway_parser(), taboo=taboo ) _args = ArgNamespace.kwargs2list(non_defaults) container_args = ['gateway'] + _args return kubernetes_deployment.get_deployment_yamls( self.dns_name, namespace=self.k8s_namespace, image_name=image_name, container_cmd='["jina"]', container_args=f'{container_args}', replicas=1, pull_policy='IfNotPresent', jina_deployment_name='gateway', pod_type=self.pod_type, port=self.common_args.port, env=cargs.env, monitoring=self.common_args.monitoring, port_monitoring=self.common_args.port_monitoring, )
def construct_runtime_container_args(cargs, uses_metas, uses_with, pod_type): """ Construct a set of Namespace arguments into a list of arguments to pass to a container entrypoint :param cargs: The namespace arguments :param uses_metas: The uses_metas to override :param uses_with: The uses_with to override :param pod_type: The pod_type :return: Arguments to pass to container """ import json from jina.helper import ArgNamespace from jina.parsers import set_pod_parser taboo = { 'uses_with', 'uses_metas', 'volumes', 'uses_before', 'uses_after', 'workspace_id', 'upload_files', 'noblock_on_start', 'env', } if pod_type == PodRoleType.HEAD: taboo.add('uses') taboo.add('workspace') if pod_type in {PodRoleType.WORKER, PodRoleType.GATEWAY}: taboo.add('polling') non_defaults = ArgNamespace.get_non_defaults_args( cargs, set_pod_parser(), taboo=taboo, ) _args = ArgNamespace.kwargs2list(non_defaults) container_args = ['executor'] + _args if uses_metas is not None: container_args.extend(['--uses-metas', json.dumps(uses_metas)]) if uses_with is not None: container_args.extend(['--uses-with', json.dumps(uses_with)]) container_args.append('--native') return container_args
def get_gateway_yamls(self, ) -> List[Dict]: import os test_pip = os.getenv('JINA_K8S_USE_TEST_PIP') is not None image_name = ('jinaai/jina:test-pip' if test_pip else f'jinaai/jina:{self.version}-py38-standard') cargs = copy.copy(self.deployment_args) cargs.env = None cargs.deployments_addresses = self.k8s_deployments_addresses from jina.helper import ArgNamespace from jina.parsers import set_gateway_parser taboo = { 'uses_with', 'uses_metas', 'volumes', 'uses_before', 'uses_after', 'workspace', 'workspace_id', 'upload_files', 'noblock_on_start', } non_defaults = ArgNamespace.get_non_defaults_args( cargs, set_gateway_parser(), taboo=taboo) _args = ArgNamespace.kwargs2list(non_defaults) container_args = ['gateway'] + _args if not cargs.k8s_connection_pool: container_args.append('--k8s-disable-connection-pool') return kubernetes_deployment.get_deployment_yamls( self.dns_name, namespace=self.k8s_namespace, image_name=image_name, container_cmd='["jina"]', container_args=f'{container_args}', replicas=1, pull_policy='IfNotPresent', jina_deployment_name='gateway', pod_type=self.pod_type, port_expose=self.common_args.port_expose, env=cargs.env, )
def _docker_run( client: 'DockerClient', args: 'argparse.Namespace', container_name: str, envs: Dict, net_mode: Optional[str], logger: 'JinaLogger', ): # important to notice, that client is not assigned as instance member to avoid potential # heavy copy into new process memory space import warnings import docker docker_version = client.version().get('Version') if not docker_version: raise DockerVersionError('docker version can not be resolved') docker_version = tuple(docker_version.split('.')) # docker daemon versions below 20.0x do not support "host.docker.internal:host-gateway" if docker_version < ('20', ): raise DockerVersionError( f'docker version {".".join(docker_version)} is below 20.0.0 and does not ' f'support "host.docker.internal:host-gateway" : https://github.com/docker/cli/issues/2664' ) if args.uses.startswith('docker://'): uses_img = args.uses.replace('docker://', '') logger.debug(f'will use Docker image: {uses_img}') else: warnings.warn( f'you are using legacy image format {args.uses}, this may create some ambiguity. ' f'please use the new format: "--uses docker://{args.uses}"') uses_img = args.uses # the image arg should be ignored otherwise it keeps using ContainerPod in the container # basically all args in Pod-docker arg group should be ignored. # this prevent setting containerPod twice from pathlib import Path from jina.helper import ArgNamespace from jina.parsers import set_pod_parser args.native = True non_defaults = ArgNamespace.get_non_defaults_args( args, set_pod_parser(), taboo={ 'uses', 'entrypoint', 'volumes', 'pull_latest', 'docker_kwargs', 'gpus', }, ) img_not_found = False try: client.images.get(uses_img) except docker.errors.ImageNotFound: logger.error(f'can not find local image: {uses_img}') img_not_found = True if img_not_found: raise BadImageNameError( f'image: {uses_img} can not be found local & remote.') _volumes = {} if not args.disable_auto_volume and not args.volumes: ( generated_volumes, workspace_in_container, ) = generate_default_volume_and_workspace( workspace_id=args.workspace_id) args.volumes = generated_volumes args.workspace = (workspace_in_container if not args.workspace else args.workspace) if args.volumes: for p in args.volumes: paths = p.split(':') local_path = paths[0] Path(os.path.abspath(local_path)).mkdir(parents=True, exist_ok=True) if len(paths) == 2: container_path = paths[1] else: container_path = '/' + os.path.basename(p) _volumes[os.path.abspath(local_path)] = { 'bind': container_path, 'mode': 'rw', } device_requests = [] if args.gpus: device_requests = get_gpu_device_requests(args.gpus) del args.gpus _args = ArgNamespace.kwargs2list(non_defaults) ports = {f'{args.port}/tcp': args.port} if not net_mode else None docker_kwargs = args.docker_kwargs or {} container = client.containers.run( uses_img, _args, detach=True, auto_remove=True, ports=ports, name=container_name, volumes=_volumes, network_mode=net_mode, entrypoint=args.entrypoint, extra_hosts={__docker_host__: 'host-gateway'}, device_requests=device_requests, environment=envs, **docker_kwargs, ) return container