def apply_params(self): self.compiled_operation = CompiledOperationSpecification.apply_params( config=self.compiled_operation, params=self.params, context=self.globals, ) self._param_spec = CompiledOperationSpecification.calculate_context_spec( config=self.compiled_operation, contexts=self.globals, should_be_resolved=True, )
def test_create_run_with_templated_service_spec(self): config_dict = get_fxt_service_with_inputs() spec = OperationSpecification.read(values=config_dict) run = compile_operation_run( project_id=self.project.id, user_id=self.user.id, op_spec=spec ) assert run.kind == V1RunKind.SERVICE assert run.name == "foo" assert run.description == "a description" assert set(run.tags) == {"backend", "lab"} job_spec = CompiledOperationSpecification.read(run.content) assert job_spec.run.container.image == "{{ image }}" compiled_operation = CompiledOperationSpecification.read(run.content) compiled_operation = CompiledOperationSpecification.apply_params( compiled_operation, params=spec.params ) compiled_operation = CompiledOperationSpecification.apply_operation_contexts( compiled_operation ) CompiledOperationSpecification.apply_runtime_contexts(compiled_operation) run.content = compiled_operation.to_dict(dump=True) run.save(update_fields=["content"]) job_spec = CompiledOperationSpecification.read(run.content) job_spec = CompiledOperationSpecification.apply_runtime_contexts(job_spec) assert job_spec.run.container.image == "foo/bar"
def resolve_connections_params(self): self.compiled_operation = CompiledOperationSpecification.apply_run_connections_params( config=self.compiled_operation, artifact_store=self.agent_config.artifacts_store.name if self.agent_config else None, contexts=self.globals, )
def resolve_params(self): params = self.run.params or {} self.compiled_operation = CompiledOperationSpecification.apply_params( config=self.compiled_operation, params=params, context=self.globals, )
def convert( owner_name: str, project_name: str, run_name: str, run_uuid: str, content: str, default_auth: bool, ) -> Dict: polypod_config = PolypodConfig() compiled_operation = CompiledOperationSpecification.read(content) polypod_config.resolve(compiled_operation=compiled_operation) return converter.convert( compiled_operation=compiled_operation, owner_name=owner_name, project_name=project_name, run_name=run_name, run_uuid=run_uuid, namespace=polypod_config.namespace, polyaxon_init=polypod_config.polyaxon_init, polyaxon_sidecar=polypod_config.polyaxon_sidecar, run_path=run_uuid, artifacts_store=polypod_config.artifacts_store, connection_by_names=polypod_config.connection_by_names, secrets=polypod_config.secrets, config_maps=polypod_config.config_maps, default_sa=polypod_config.default_sa, converters=PLATFORM_CONVERTERS, default_auth=default_auth, )
def apply_content(self): try: self.compiled_operation = CompiledOperationSpecification.apply_context( self.compiled_operation) except Exception as e: raise PolyaxonCompilerError( "Could not apply run context, error: {}".format(repr(e)))
def generate(polyaxonfile, python_module, build_context, destination, copy_path, params, track): """Generate a dockerfile given the polyaxonfile.""" from polyaxon.init.dockerfile import create_dockerfile_lineage from polyaxon.utils.hashing import hash_value if all([polyaxonfile, build_context]): Printer.print_error( "Only a polyaxonfile or a build context option is required.") sys.exit(1) if build_context: try: build_context = [ V1DockerfileType.from_dict(ConfigSpec.read_from(build_context)) ] except (PolyaxonSchemaError, ValidationError) as e: Printer.print_error("received a non valid build context.") Printer.print_error("Error message: {}.".format(e)) sys.exit(1) else: specification = check_polyaxonfile( polyaxonfile=polyaxonfile, python_module=python_module, params=params, verbose=False, ) try: compiled_operation = OperationSpecification.compile_operation( specification) compiled_operation.apply_params(params=specification.config.params) compiled_operation = CompiledOperationSpecification.apply_operation_contexts( compiled_operation) except PolyaxonSchemaError: Printer.print_error( "Could not run this polyaxonfile locally, " "a context is required to resolve it dependencies.") sys.exit(1) build_context = compiled_operation.init_dockerfiles for init_dockerfile in build_context: generator = DockerFileGenerator(build_context=init_dockerfile, destination=destination or ".") generator.create() Printer.print_success("Dockerfile was generated, path: `{}`".format( generator.dockerfile_path)) dockerfile_path = generator.dockerfile_path if copy_path: dockerfile_path = copy_file(dockerfile_path, copy_path) if track: hash_content = hash_value(init_dockerfile.to_dict()) create_dockerfile_lineage(dockerfile_path, summary={"hash": hash_content})
def apply_operation_contexts(self): try: self.compiled_operation = CompiledOperationSpecification.apply_operation_contexts( self.compiled_operation, param_spec=self._param_spec, contexts=self.globals, ) except Exception as e: raise PolyaxonCompilerError( "Could not apply run context, error: {}".format(repr(e)))
def test_copy_run(self, auditor_record): run = copy_run(run=self.run) assert auditor_record.call_count == 1 call_args, call_kwargs = auditor_record.call_args assert call_kwargs["event_type"] == run_events.RUN_CREATED assert run.user == self.run.user assert run.kind == self.run.kind assert run.project == self.run.project assert run.name == self.run.name assert run.description == self.run.description assert run.content != self.run.content config = CompiledOperationSpecification.read(run.content) original_config = CompiledOperationSpecification.read(self.run.content) assert len(config.run.init or []) == len(original_config.run.init or []) + 1 assert run.raw_content == self.run.raw_content assert run.readme == self.run.readme assert run.tags == self.run.tags assert run.cloning_kind == V1CloningKind.COPY assert run.original == self.run assert run.inputs == {"image": "foo/bar"} run = copy_run( run=self.run, user_id=self.user2.id, name="new-name", description="new-description", content={"trigger": "all_done"}, readme="new-readme", tags=["tag1", "tag2"], ) assert run.user != self.run.user assert run.user == self.user2 assert run.project == self.project assert run.name == "new-name" assert run.description == "new-description" assert run.content != self.run.content assert run.raw_content == self.run.raw_content assert run.readme == "new-readme" assert set(run.tags) == {"tag1", "tag2"} assert run.inputs == {"image": "foo/bar"} assert run.cloning_kind == V1CloningKind.COPY assert run.original == self.run
def test_create_run_with_service_spec(self): config_dict = get_fxt_service() spec = OperationSpecification.read(values=config_dict) run = compile_operation_run( project_id=self.project.id, user_id=self.user.id, op_spec=spec ) assert run.kind == V1RunKind.SERVICE assert run.name == "foo" assert run.description == "a description" assert set(run.tags) == {"backend", "lab", "tag1", "tag2"} service_spec = CompiledOperationSpecification.read(run.content) assert service_spec.run.container.image == "jupyter"
def _run(ctx, name, owner, project_name, description, tags, specification, log): docker = DockerOperator() if not docker.check(): raise PolyaxonException("Docker is required to run this command.") # Create Build project = "{}.{}".format(owner, project_name) build_job = Run(project=project) specification = CompiledOperationSpecification.apply_operation_contexts( specification) content = specification.to_dict(dump=True) build_job.create(name=name, description=description, tags=tags, content=content) image = _create_docker_build(build_job, specification, project) experiment = Run(project=project) experiment.create(name=name, tags=tags, description=description, content=content) cmd_args = ["run", "--rm"] data_paths, bind_mounts = _get_data_bind_mounts(specification.data_refs) for key, value in _get_env_vars( project=project, experiment_id=experiment.experiment_id, params=specification.params, data_paths=data_paths, ): cmd_args += ["-e", "{key}={value}".format(key=key, value=value)] cmd_args += _get_config_volume() cmd_args += _get_data_volumes(bind_mounts) cmd_args += [image] # Add cmd.run _, args = specification.container.get_container_command_args() for arg in args: cmd_args += arg try: print(cmd_args) docker.execute(cmd_args, stream=True) except Exception as e: handle_cli_error(e, message="Could start local run.") sys.exit(1)
def _apply_runtime_contexts(self): contexts = resolve_contexts( namespace=self.namespace, owner_name=self.owner_name, project_name=self.project_name, project_uuid=self.project_uuid, run_name=self.run_name, run_path=self.run_path, run_uuid=self.run_uuid, compiled_operation=self.compiled_operation, connection_by_names=self.connection_by_names, artifacts_store=self.artifacts_store, iteration=self.iteration, created_at=self.created_at, compiled_at=self.compiled_at, ) return CompiledOperationSpecification.apply_runtime_contexts( self.compiled_operation, contexts=contexts)
def test_create_run_with_job_spec(self): config_dict = get_fxt_job() spec = OperationSpecification.read(values=config_dict) run = compile_operation_run(project_id=self.project.id, user_id=self.user.id, op_spec=spec) assert run.kind == V1RunKind.JOB assert run.name == "foo" assert run.description == "a description" assert set(run.tags) == {"tag1", "tag2"} # Check compiled operation passes compiled_operation = CompiledOperationSpecification.read(run.content) compiled_operation = CompiledOperationSpecification.apply_params( compiled_operation) CompiledOperationSpecification.apply_run_contexts(compiled_operation, ) # Check job job_spec = CompiledOperationSpecification.read(run.content) assert job_spec.run.container.image == "test" job_spec = CompiledOperationSpecification.apply_context(job_spec) assert job_spec.run.container.image == "test"
def test_copy_run(self, auditor_record): run = copy_run(run=self.run) assert auditor_record.call_count == 1 call_args, call_kwargs = auditor_record.call_args assert call_kwargs["event_type"] == run_events.RUN_CREATED assert run.user == self.run.user assert run.kind == self.run.kind assert run.project == self.run.project assert run.name == self.run.name assert run.description == self.run.description assert run.content == self.run.content assert run.meta_info == {META_COPY_ARTIFACTS: {"dirs": [self.run.uuid.hex]}} config = CompiledOperationSpecification.read(run.content) original_config = CompiledOperationSpecification.read(self.run.content) assert len(config.run.init or []) == len(original_config.run.init or []) assert run.raw_content == self.run.raw_content assert run.readme == self.run.readme assert run.tags == self.run.tags assert run.cloning_kind == V1CloningKind.COPY assert run.original == self.run assert run.inputs == {"image": "foo/bar"} run = copy_run( run=self.run, user_id=self.user2.id, name="new-name", description="new-description", content={"trigger": "all_done"}, readme="new-readme", tags=["tag1", "tag2"], ) assert run.user != self.run.user assert run.user == self.user2 assert run.project == self.project assert run.name == "new-name" assert run.description == "new-description" assert run.content != self.run.content assert run.raw_content == self.run.raw_content assert run.meta_info == {META_COPY_ARTIFACTS: {"dirs": [self.run.uuid.hex]}} assert run.readme == "new-readme" assert set(run.tags) == {"tag1", "tag2"} assert run.inputs == {"image": "foo/bar"} assert run.cloning_kind == V1CloningKind.COPY assert run.original == self.run # Copy with uploads self.run.meta_info[META_UPLOAD_ARTIFACTS] = "foo" self.run.save() run = copy_run( run=self.run, user_id=self.user2.id, name="new-name", description="new-description", content={"trigger": "all_done"}, readme="new-readme", tags=["tag1", "tag2"], ) assert run.user != self.run.user assert run.user == self.user2 assert run.project == self.project assert run.name == "new-name" assert run.description == "new-description" assert run.content != self.run.content assert run.raw_content == self.run.raw_content assert run.meta_info == { META_UPLOAD_ARTIFACTS: "foo", META_COPY_ARTIFACTS: {"dirs": [self.run.uuid.hex]}, } assert run.readme == "new-readme" assert set(run.tags) == {"tag1", "tag2"} assert run.inputs == {"image": "foo/bar"} assert run.cloning_kind == V1CloningKind.COPY assert run.original == self.run # Copy with uploads and specific fields self.run.meta_info[META_UPLOAD_ARTIFACTS] = "foo" self.run.save() run = copy_run( run=self.run, user_id=self.user2.id, name="new-name", description="new-description", content={"trigger": "all_done"}, readme="new-readme", tags=["tag1", "tag2"], meta_info={ META_COPY_ARTIFACTS: { "dirs": ["{}/resources".format(self.run.uuid.hex)] } }, ) assert run.user != self.run.user assert run.user == self.user2 assert run.project == self.project assert run.name == "new-name" assert run.description == "new-description" assert run.content != self.run.content assert run.raw_content == self.run.raw_content assert run.meta_info == { META_UPLOAD_ARTIFACTS: "foo", META_COPY_ARTIFACTS: {"dirs": ["{}/resources".format(self.run.uuid.hex)]}, } assert run.readme == "new-readme" assert set(run.tags) == {"tag1", "tag2"} assert run.inputs == {"image": "foo/bar"} assert run.cloning_kind == V1CloningKind.COPY assert run.original == self.run
def _apply_runtime_contexts(self): contexts = self._resolve_contexts() return CompiledOperationSpecification.apply_runtime_contexts( self.compiled_operation, contexts=contexts )
def apply_contexts(self): self.compiled_operation = CompiledOperationSpecification.apply_run_contexts( self.compiled_operation, contexts=self.contexts)
def run( ctx, project, polyaxonfile, python_module, url, hub, name, tags, description, upload, log, watch, local, conda_env, params, profile, queue, nocache, ): """Run polyaxonfile specification. Examples: \b $ polyaxon run -f file -f file_override ... Upload before running \b $ polyaxon run -f file -u Run and set description and tags for this run \b $ polyaxon run -f file -u --description="Description of the current run" --tags="foo, bar, moo" Run and set a unique name for this run \b polyaxon run --name=foo Run for a specific project \b $ polyaxon run -p project1 -f file.yaml Run with updated params \b $ polyaxon run -p project1 -f file.yaml -P param1=234.2 -P param2=relu If a python file contains a component main, you can run that component \b polyaxon run -pm path/to/my-component.py If a python file contains more than one component, you can specify the component to run \b polyaxon run -pm path/to/my-component.py:componentA """ op_spec = check_polyaxonfile( polyaxonfile=polyaxonfile, python_module=python_module, url=url, hub=hub, params=params, profile=profile, queue=queue, nocache=nocache, log=False, ) owner, project_name = get_project_or_local(project, is_cli=True) tags = validate_tags(tags) if local: try: compiled_operation = OperationSpecification.compile_operation(op_spec) compiled_operation = CompiledOperationSpecification.apply_context( compiled_operation ) except (PolyaxonSchemaError, ValidationError): Printer.print_error( "Could not run this polyaxonfile locally, " "a context is required to resolve it dependencies." ) sys.exit(1) docker_run( ctx=ctx, name=name, owner=owner, project_name=project_name, description=description, tags=tags, compiled_operation=compiled_operation, log=log, ) elif settings.CLIENT_CONFIG.no_api: k8s_run( ctx=ctx, name=name, owner=owner, project_name=project_name, description=description, tags=tags, op_spec=op_spec, upload=upload, log=log, can_upload=all([upload, project]), ) else: platform_run( ctx=ctx, name=name, owner=owner, project_name=project_name, description=description, tags=tags, op_spec=op_spec, upload=upload, log=log, watch=watch, can_upload=all([upload, project]), )
def run( ctx, project, polyaxonfile, python_module, url, hub, name, tags, description, log, upload, upload_from, upload_to, watch, local, params, presets, queue, nocache, cache, eager, git_preset, git_revision, ignore_template, ): """Run polyaxonfile specification. Examples: \b $ polyaxon run -f file -f file_override ... Run and set description and tags for this run \b $ polyaxon run -f file --description="Description of the current run" --tags="foo, bar, moo" Run and set a unique name for this run \b polyaxon run --name=foo Run for a specific project \b $ polyaxon run -p project1 -f file.yaml Run with updated params \b $ polyaxon run -p project1 -f file.yaml -P param1=234.2 -P param2=relu If a python file contains a component main, you can run that component \b $ polyaxon run -pm path/to/my-component.py If a python file contains more than one component, you can specify the component to run \b $ polyaxon run -pm path/to/my-component.py:componentA Uploading from everything in the current folder to the default uploads path \b $ polyaxon run ... -u Uploading from everything in the current folder to a custom path, e.g. code \b $ polyaxon run ... -u-to code Uploading from everything from a sub-folder, e.g. ./code to the a custom path, e.g. new-code \b $ polyaxon run ... -u-from ./code -u-to new-code """ if cache and nocache: Printer.print_error( "You can't use `--cache` and `--nocache` at the same.", sys_exit=True ) if (upload_to or upload_from) and not upload: upload = True if upload and eager: Printer.print_error( "You can't use `--upload` and `--eager` at the same.", sys_exit=True ) git_init = None if git_preset or git_revision: # Check that the current path was initialized if not GitConfigManager.is_initialized(): Printer.print_error( "You can't use `--git-preset [--git-revision]`, " "the current path is not initialized with a valid git connection or a git url, " "please run `polyaxon init [--git-connection] [--git-url]` " "to set a valid git configuration.", sys_exit=True, ) git_init = GitConfigManager.get_config() if git_init.git is None: GitConfigManager.purge(visibility=GitConfigManager.VISIBILITY_LOCAL) Printer.print_error( "Polyaxon could not start a new run with the `[--git-preset] or [--git-revision]`. " "The current path is initialized with " "an invalid git connection or an invalid git url.\n" "please run `polyaxon init [--git-connection] [--git-url]` " "to properly initialize the current path.", sys_exit=True, ) if git_revision: git_init.git.revision = git_revision elif code_reference.is_git_initialized(path="."): if code_reference.is_dirty(path="."): Printer.print_warning( "Polyaxon detected uncommitted changes in the current git repo!" ) commit_hash = code_reference.get_commit() git_init.git.revision = commit_hash else: Printer.print_warning( "Polyaxon could not find a valid git repo, " "and will not add the current commit to the git initializer." ) presets = validate_tags(presets) op_spec = check_polyaxonfile( polyaxonfile=polyaxonfile, python_module=python_module, url=url, hub=hub, params=params, presets=presets, queue=queue, cache=cache, nocache=nocache, verbose=False, eager=eager, git_init=git_init, ignore_template=ignore_template, ) if ignore_template: op_spec.disable_template() if op_spec.is_template(): click.echo("Please customize the specification or disable the template.") sys.exit(1) owner, project_name = get_project_or_local(project, is_cli=True) tags = validate_tags(tags) if local: try: compiled_operation = OperationSpecification.compile_operation(op_spec) compiled_operation = ( CompiledOperationSpecification.apply_operation_contexts( compiled_operation ) ) except (PolyaxonSchemaError, ValidationError): Printer.print_error( "Could not run this polyaxonfile locally, " "a context is required to resolve it dependencies." ) sys.exit(1) docker_run( ctx=ctx, name=name, owner=owner, project_name=project_name, description=description, tags=tags, compiled_operation=compiled_operation, log=log, ) elif settings.CLIENT_CONFIG.no_api: k8s_run( ctx=ctx, name=name, owner=owner, project_name=project_name, description=description, tags=tags, op_spec=op_spec, log=log, ) else: platform_run( ctx=ctx, name=name, owner=owner, project_name=project_name, description=description, tags=tags, op_spec=op_spec, log=log, upload=upload, upload_to=upload_to, upload_from=upload_from, watch=watch, eager=eager, )
def run( ctx, project, polyaxonfile, python_module, url, hub, name, tags, description, log, watch, local, params, presets, queue, nocache, eager, git_preset, git_revision, ignore_template, ): """Run polyaxonfile specification. Examples: \b $ polyaxon run -f file -f file_override ... Run and set description and tags for this run \b $ polyaxon run -f file --description="Description of the current run" --tags="foo, bar, moo" Run and set a unique name for this run \b polyaxon run --name=foo Run for a specific project \b $ polyaxon run -p project1 -f file.yaml Run with updated params \b $ polyaxon run -p project1 -f file.yaml -P param1=234.2 -P param2=relu If a python file contains a component main, you can run that component \b polyaxon run -pm path/to/my-component.py If a python file contains more than one component, you can specify the component to run \b polyaxon run -pm path/to/my-component.py:componentA """ git_init = None if git_preset: # Check that the current path was initialized if not GitConfigManager.is_initialized(): Printer.print_error( "You can't use --git-init, " "the current path is not initialized with a valid git connection or a git url, " "please run `polyaxon init [--git-connection] [--git-url]` " "to set a valid git configuration.") sys.exit(1) git_init = GitConfigManager.get_config() if git_revision: git_init.git.revision = git_revision elif code_reference.is_git_initialized(path="."): if code_reference.is_dirty(path="."): Printer.print_warning( "Polyaxon detected uncommitted changes in the current git repo!" ) commit_hash = code_reference.get_commit() git_init.git.revision = commit_hash else: Printer.print_warning( "Polyaxon could not find a valid git repo, " "and will not add the current commit to the git initializer.") presets = validate_tags(presets) op_spec = check_polyaxonfile( polyaxonfile=polyaxonfile, python_module=python_module, url=url, hub=hub, params=params, presets=presets, queue=queue, nocache=nocache, verbose=False, eager=eager, git_init=git_init, ignore_template=ignore_template, ) if ignore_template: op_spec.disable_template() if op_spec.is_template(): click.echo( "Please customize the specification or disable the template.") sys.exit(1) owner, project_name = get_project_or_local(project, is_cli=True) tags = validate_tags(tags) if local: try: compiled_operation = OperationSpecification.compile_operation( op_spec) compiled_operation = CompiledOperationSpecification.apply_operation_contexts( compiled_operation) except (PolyaxonSchemaError, ValidationError): Printer.print_error( "Could not run this polyaxonfile locally, " "a context is required to resolve it dependencies.") sys.exit(1) docker_run( ctx=ctx, name=name, owner=owner, project_name=project_name, description=description, tags=tags, compiled_operation=compiled_operation, log=log, ) elif settings.CLIENT_CONFIG.no_api: k8s_run( ctx=ctx, name=name, owner=owner, project_name=project_name, description=description, tags=tags, op_spec=op_spec, log=log, ) else: platform_run( ctx=ctx, name=name, owner=owner, project_name=project_name, description=description, tags=tags, op_spec=op_spec, log=log, watch=watch, eager=eager, )