diff --git a/CHANGELOG.D/652.feature b/CHANGELOG.D/652.feature
new file mode 100644
index 000000000..840410779
--- /dev/null
+++ b/CHANGELOG.D/652.feature
@@ -0,0 +1 @@
+Implement *job run* command.
\ No newline at end of file
diff --git a/README.md b/README.md
index 02e59fe04..43456528f 100644
--- a/README.md
+++ b/README.md
@@ -4,6 +4,7 @@
* [Preface](#Preface)
* [neuro](#neuro)
* [neuro job](#neuro-job)
+ * [neuro job run](#neuro-job-run)
* [neuro job submit](#neuro-job-submit)
* [neuro job ls](#neuro-job-ls)
* [neuro job status](#neuro-job-status)
@@ -33,6 +34,7 @@
* [neuro completion generate](#neuro-completion-generate)
* [neuro completion patch](#neuro-completion-patch)
* [neuro help](#neuro-help)
+ * [neuro run](#neuro-run)
* [neuro submit](#neuro-submit)
* [neuro ps](#neuro-ps)
* [neuro status](#neuro-status)
@@ -102,6 +104,7 @@ Name | Description|
|Usage|Description|
|---|---|
| _[neuro help](#neuro-help)_| Get help on a command |
+| _[neuro run](#neuro-run)_| Run an image with predefined configuration |
| _[neuro submit](#neuro-submit)_| Submit an image to run on the cluster |
| _[neuro ps](#neuro-ps)_| List all jobs |
| _[neuro status](#neuro-status)_| Display status of a job |
@@ -146,6 +149,7 @@ Name | Description|
|Usage|Description|
|---|---|
+| _[neuro job run](#neuro-job-run)_| Run an image with predefined configuration |
| _[neuro job submit](#neuro-job-submit)_| Submit an image to run on the cluster |
| _[neuro job ls](#neuro-job-ls)_| List all jobs |
| _[neuro job status](#neuro-job-status)_| Display status of a job |
@@ -158,6 +162,48 @@ Name | Description|
+### neuro job run
+
+Run an image with predefined configuration.
IMAGE container image name.
CMD list will be passed as commands to model container.
+
+**Usage:**
+
+```bash
+neuro job run [OPTIONS] IMAGE [CMD]...
+```
+
+**Examples:**
+
+```bash
+
+# Starts a container pytorch:latest with two paths mounted.
+# Directory storage:// is mounted as /var/storage/home in read-write mode,
+# storage://neuromation is mounted as :/var/storage/neuromation as read-only.
+neuro run pytorch:latest --volume=HOME
+
+```
+
+**Options:**
+
+Name | Description|
+|----|------------|
+|_\-s, --preset PRESET_|Predefined job profile \[default: gpu-small]|
+|_\-x, --extshm / -X, --no-extshm_|Request extended '/dev/shm' space \[default: True]|
+|_--http INTEGER_|Enable HTTP port forwarding to container \[default: 80]|
+|_\--http-auth / --no-http-auth_|Enable HTTP authentication for forwarded HTTP port \[default: True]|
+|_\-p, --preemptible / -P, --non-preemptible_|Run job on a lower-cost preemptible instance \[default: True]|
+|_\-n, --name NAME_|Optional job name|
+|_\-d, --description DESC_|Add optional description in free format|
+|_\-q, --quiet_|Run command in quiet mode \(print only job id)|
+|_\-v, --volume MOUNT_|Mounts directory from vault into container. Use multiple options to mount more than one volume. --volume=HOME is an alias for storage://~:/var/storage/home:rw and storage://neuromation:/var/storage/neuromation:ro|
+|_\-e, --env VAR=VAL_|Set environment variable in container Use multiple options to define more than one variable|
+|_\--env-file PATH_|File with environment variables to pass|
+|_\--wait-start / --no-wait-start_|Wait for a job start or failure \[default: True]|
+|_--help_|Show this message and exit.|
+
+
+
+
### neuro job submit
Submit an image to run on the cluster.
IMAGE container image name.
CMD list will be passed as commands to model container.
@@ -194,7 +240,7 @@ Name | Description|
|_\-n, --name NAME_|Optional job name|
|_\-d, --description DESC_|Optional job description in free format|
|_\-q, --quiet_|Run command in quiet mode \(print only job id)|
-|_\-v, --volume MOUNT_|Mounts directory from vault into container. Use multiple options to mount more than one volume|
+|_\-v, --volume MOUNT_|Mounts directory from vault into container. Use multiple options to mount more than one volume. --volume=HOME is an alias for storage://~:/var/storage/home:rw and storage://neuromation:/var/storage/neuromation:ro|
|_\-e, --env VAR=VAL_|Set environment variable in container Use multiple options to define more than one variable|
|_\--env-file PATH_|File with environment variables to pass|
|_\--wait-start / --no-wait-start_|Wait for a job start or failure \[default: True]|
@@ -859,6 +905,48 @@ Name | Description|
+## neuro run
+
+Run an image with predefined configuration.
IMAGE container image name.
CMD list will be passed as commands to model container.
+
+**Usage:**
+
+```bash
+neuro run [OPTIONS] IMAGE [CMD]...
+```
+
+**Examples:**
+
+```bash
+
+# Starts a container pytorch:latest with two paths mounted.
+# Directory storage:// is mounted as /var/storage/home in read-write mode,
+# storage://neuromation is mounted as :/var/storage/neuromation as read-only.
+neuro run pytorch:latest --volume=HOME
+
+```
+
+**Options:**
+
+Name | Description|
+|----|------------|
+|_\-s, --preset PRESET_|Predefined job profile \[default: gpu-small]|
+|_\-x, --extshm / -X, --no-extshm_|Request extended '/dev/shm' space \[default: True]|
+|_--http INTEGER_|Enable HTTP port forwarding to container \[default: 80]|
+|_\--http-auth / --no-http-auth_|Enable HTTP authentication for forwarded HTTP port \[default: True]|
+|_\-p, --preemptible / -P, --non-preemptible_|Run job on a lower-cost preemptible instance \[default: True]|
+|_\-n, --name NAME_|Optional job name|
+|_\-d, --description DESC_|Add optional description in free format|
+|_\-q, --quiet_|Run command in quiet mode \(print only job id)|
+|_\-v, --volume MOUNT_|Mounts directory from vault into container. Use multiple options to mount more than one volume. --volume=HOME is an alias for storage://~:/var/storage/home:rw and storage://neuromation:/var/storage/neuromation:ro|
+|_\-e, --env VAR=VAL_|Set environment variable in container Use multiple options to define more than one variable|
+|_\--env-file PATH_|File with environment variables to pass|
+|_\--wait-start / --no-wait-start_|Wait for a job start or failure \[default: True]|
+|_--help_|Show this message and exit.|
+
+
+
+
## neuro submit
Submit an image to run on the cluster.
IMAGE container image name.
CMD list will be passed as commands to model container.
@@ -895,7 +983,7 @@ Name | Description|
|_\-n, --name NAME_|Optional job name|
|_\-d, --description DESC_|Optional job description in free format|
|_\-q, --quiet_|Run command in quiet mode \(print only job id)|
-|_\-v, --volume MOUNT_|Mounts directory from vault into container. Use multiple options to mount more than one volume|
+|_\-v, --volume MOUNT_|Mounts directory from vault into container. Use multiple options to mount more than one volume. --volume=HOME is an alias for storage://~:/var/storage/home:rw and storage://neuromation:/var/storage/neuromation:ro|
|_\-e, --env VAR=VAL_|Set environment variable in container Use multiple options to define more than one variable|
|_\--env-file PATH_|File with environment variables to pass|
|_\--wait-start / --no-wait-start_|Wait for a job start or failure \[default: True]|
diff --git a/neuromation/api/jobs.py b/neuromation/api/jobs.py
index ad82a3ecf..49240aaf6 100644
--- a/neuromation/api/jobs.py
+++ b/neuromation/api/jobs.py
@@ -152,14 +152,6 @@ def from_cli(cls, username: str, volume: str) -> "Volume":
read_only=read_only,
)
- @classmethod
- def from_cli_list(
- cls, username: str, lst: Sequence[str]
- ) -> Optional[List["Volume"]]:
- if not lst:
- return None
- return [cls.from_cli(username, s) for s in lst]
-
@dataclass(frozen=True)
class HTTPPort:
diff --git a/neuromation/cli/job.py b/neuromation/cli/job.py
index 41a5748c5..87d78a2ed 100644
--- a/neuromation/cli/job.py
+++ b/neuromation/cli/job.py
@@ -3,7 +3,9 @@
import os
import shlex
import sys
-from typing import List, Sequence, Tuple
+from dataclasses import dataclass
+from types import MappingProxyType
+from typing import Dict, List, Optional, Sequence, Set, Tuple
import click
@@ -50,6 +52,43 @@
log = logging.getLogger(__name__)
+@dataclass(frozen=True)
+class RunPreset:
+ cpu: float
+ memory: int
+ gpu: Optional[int]
+ gpu_model: Optional[str]
+
+
+RUN_PRESET = MappingProxyType(
+ {
+ "gpu-small": RunPreset(gpu=1, cpu=7, memory=30 * 1024, gpu_model=GPU_MODELS[0]),
+ "gpu-large": RunPreset(
+ gpu=1, cpu=7, memory=60 * 1024, gpu_model=GPU_MODELS[-1]
+ ),
+ "cpu-small": RunPreset(gpu=None, cpu=2, memory=2 * 1024, gpu_model=None),
+ "cpu-large": RunPreset(gpu=None, cpu=3, memory=14 * 1024, gpu_model=None),
+ }
+)
+
+
+def build_env(env: Sequence[str], env_file: str) -> Dict[str, str]:
+ if env_file:
+ with open(env_file, "r") as ef:
+ env = ef.read().splitlines() + list(env)
+
+ env_dict = {}
+ for line in env:
+ splitted = line.split("=", 1)
+ if len(splitted) == 1:
+ val = os.environ.get(splitted[0], "")
+ env_dict[splitted[0]] = val
+ else:
+ env_dict[splitted[0]] = splitted[1]
+
+ return env_dict
+
+
@group()
def job() -> None:
"""
@@ -142,7 +181,9 @@ def job() -> None:
metavar="MOUNT",
multiple=True,
help="Mounts directory from vault into container. "
- "Use multiple options to mount more than one volume",
+ "Use multiple options to mount more than one volume. "
+ "--volume=HOME is an alias for storage://~:/var/storage/home:rw and "
+ "storage://neuromation:/var/storage/neuromation:ro",
)
@click.option(
"-e",
@@ -167,8 +208,8 @@ def job() -> None:
async def submit(
root: Root,
image: DockerImage,
- gpu: int,
- gpu_model: str,
+ gpu: Optional[int],
+ gpu_model: Optional[str],
cpu: float,
memory: int,
extshm: bool,
@@ -179,7 +220,7 @@ async def submit(
env: Sequence[str],
env_file: str,
preemptible: bool,
- name: str,
+ name: Optional[str],
description: str,
quiet: bool,
wait_start: bool,
@@ -199,59 +240,26 @@ async def submit(
neuro submit --volume storage:/q1:/qm:ro --volume storage:/mod:/mod:rw \
pytorch:latest
"""
-
- username = root.username
-
- # TODO (Alex Davydow 12.12.2018): Consider splitting env logic into
- # separate function.
- if env_file:
- with open(env_file, "r") as ef:
- env = ef.read().splitlines() + list(env)
-
- env_dict = {}
- for line in env:
- splitted = line.split("=", 1)
- if len(splitted) == 1:
- val = os.environ.get(splitted[0], "")
- env_dict[splitted[0]] = val
- else:
- env_dict[splitted[0]] = splitted[1]
-
- cmd = " ".join(cmd) if cmd is not None else None
- log.debug(f'cmd="{cmd}"')
-
- # TODO (ajuszkowski 01-Feb-19) process --quiet globally to set up logger+click
- if not quiet:
- log.info(f"Using image '{image.as_url_str()}'")
- log.debug(f"IMAGE: {image}")
- image_obj = Image(image=image.as_repo_str(), command=cmd)
-
- network = NetworkPortForwarding.from_cli(http, http_auth)
- resources = Resources.create(cpu, gpu, gpu_model, memory, extshm)
- volumes = Volume.from_cli_list(username, volume)
- if volumes and not quiet:
- log.info(
- "Using volumes: \n"
- + "\n".join(f" {volume_to_verbose_str(v)}" for v in volumes)
- )
-
- job = await root.client.jobs.submit(
- image=image_obj,
- resources=resources,
- network=network,
- volumes=volumes,
- is_preemptible=preemptible,
+ await run_job(
+ root,
+ image=image,
+ gpu=gpu,
+ gpu_model=gpu_model,
+ cpu=cpu,
+ memory=memory,
+ extshm=extshm,
+ http=http,
+ http_auth=http_auth,
+ cmd=cmd,
+ volume=volume,
+ env=env,
+ env_file=env_file,
+ preemptible=preemptible,
name=name,
description=description,
- env=env_dict,
+ quiet=quiet,
+ wait_start=wait_start,
)
- click.echo(JobFormatter(quiet)(job))
- progress = JobStartProgress.create(tty=root.tty, color=root.color, quiet=quiet)
- while wait_start and job.status == JobStatus.PENDING:
- await asyncio.sleep(0.2)
- job = await root.client.jobs.status(job.id)
- progress(job)
- progress.close()
@command(context_settings=dict(ignore_unknown_options=True))
@@ -460,6 +468,151 @@ def format_fail(job: str, reason: Exception) -> str:
click.echo(format_fail(job, error))
+@command(context_settings=dict(ignore_unknown_options=True))
+@click.argument("image", type=ImageType())
+@click.argument("cmd", nargs=-1, type=click.UNPROCESSED)
+@click.option(
+ "-s",
+ "--preset",
+ metavar="PRESET",
+ type=click.Choice(list(RUN_PRESET)),
+ help="Predefined job profile",
+ default="gpu-small",
+ show_default=True,
+)
+@click.option(
+ "-x/-X",
+ "--extshm/--no-extshm",
+ is_flag=True,
+ default=True,
+ show_default=True,
+ help="Request extended '/dev/shm' space",
+)
+@click.option(
+ "--http",
+ type=int,
+ default=80,
+ show_default=True,
+ help="Enable HTTP port forwarding to container",
+)
+@click.option(
+ "--http-auth/--no-http-auth",
+ is_flag=True,
+ help="Enable HTTP authentication for forwarded HTTP port",
+ default=True,
+ show_default=True,
+)
+@click.option(
+ "--preemptible/--non-preemptible",
+ "-p/-P",
+ help="Run job on a lower-cost preemptible instance",
+ default=True,
+ show_default=True,
+)
+@click.option(
+ "-n",
+ "--name",
+ metavar="NAME",
+ type=str,
+ help="Optional job name",
+ default=None,
+ show_default=True,
+)
+@click.option(
+ "-d",
+ "--description",
+ metavar="DESC",
+ help="Add optional description in free format",
+)
+@click.option(
+ "-q", "--quiet", is_flag=True, help="Run command in quiet mode (print only job id)"
+)
+@click.option(
+ "-v",
+ "--volume",
+ metavar="MOUNT",
+ multiple=True,
+ help="Mounts directory from vault into container. "
+ "Use multiple options to mount more than one volume. "
+ "--volume=HOME is an alias for storage://~:/var/storage/home:rw and "
+ "storage://neuromation:/var/storage/neuromation:ro",
+)
+@click.option(
+ "-e",
+ "--env",
+ metavar="VAR=VAL",
+ multiple=True,
+ help="Set environment variable in container "
+ "Use multiple options to define more than one variable",
+)
+@click.option(
+ "--env-file",
+ type=click.Path(exists=True),
+ help="File with environment variables to pass",
+)
+@click.option(
+ "--wait-start/--no-wait-start",
+ default=True,
+ show_default=True,
+ help="Wait for a job start or failure",
+)
+@async_cmd()
+async def run(
+ root: Root,
+ image: DockerImage,
+ preset: str,
+ extshm: bool,
+ http: int,
+ http_auth: bool,
+ cmd: Sequence[str],
+ volume: Sequence[str],
+ env: Sequence[str],
+ env_file: str,
+ preemptible: bool,
+ name: Optional[str],
+ description: str,
+ quiet: bool,
+ wait_start: bool,
+) -> None:
+ """
+ Run an image with predefined configuration.
+
+ IMAGE container image name.
+
+ CMD list will be passed as commands to model container.
+
+ Examples:
+
+ # Starts a container pytorch:latest with two paths mounted.
+ # Directory storage:// is mounted as /var/storage/home in read-write mode,
+ # storage://neuromation is mounted as :/var/storage/neuromation as read-only.
+ neuro run pytorch:latest --volume=HOME
+ """
+ job_preset = RUN_PRESET[preset]
+
+ await run_job(
+ root,
+ image=image,
+ gpu=job_preset.gpu,
+ gpu_model=job_preset.gpu_model,
+ cpu=job_preset.cpu,
+ memory=job_preset.memory,
+ extshm=extshm,
+ http=http,
+ http_auth=http_auth,
+ cmd=cmd,
+ volume=volume,
+ env=env,
+ env_file=env_file,
+ preemptible=preemptible,
+ name=name,
+ description=description,
+ quiet=quiet,
+ wait_start=wait_start,
+ )
+
+
+job.add_command(run)
job.add_command(submit)
job.add_command(ls)
job.add_command(status)
@@ -472,3 +625,77 @@ def format_fail(job: str, reason: Exception) -> str:
job.add_command(alias(ls, "list", hidden=True))
job.add_command(alias(logs, "monitor", hidden=True))
+
+
+async def run_job(
+ root: Root,
+ *,
+ image: DockerImage,
+ gpu: Optional[int],
+ gpu_model: Optional[str],
+ cpu: float,
+ memory: int,
+ extshm: bool,
+ http: int,
+ http_auth: bool,
+ cmd: Sequence[str],
+ volume: Sequence[str],
+ env: Sequence[str],
+ env_file: str,
+ preemptible: bool,
+ name: Optional[str],
+ description: str,
+ quiet: bool,
+ wait_start: bool,
+) -> None:
+ username = root.username
+
+ env_dict = build_env(env, env_file)
+
+ cmd = " ".join(cmd) if cmd is not None else None
+ log.debug(f'cmd="{cmd}"')
+
+ # TODO (ajuszkowski 01-Feb-19) process --quiet globally to set up logger+click
+ if not quiet:
+ log.info(f"Using image '{image.as_url_str()}'")
+ log.debug(f"IMAGE: {image}")
+ image_obj = Image(image=image.as_repo_str(), command=cmd)
+
+ network = NetworkPortForwarding.from_cli(http, http_auth)
+ resources = Resources.create(cpu, gpu, gpu_model, memory, extshm)
+
+ volumes: Set[Volume] = set()
+ for v in volume:
+ if v == "HOME":
+ volumes.add(Volume.from_cli(username, "storage://~:/var/storage/home:rw"))
+ volumes.add(
+ Volume.from_cli(
+ username, "storage://neuromation:/var/storage/neuromation:ro"
+ )
+ )
+ else:
+ volumes.add(Volume.from_cli(username, v))
+
+ if volumes and not quiet:
+ log.info(
+ "Using volumes: \n"
+ + "\n".join(f" {volume_to_verbose_str(v)}" for v in volumes)
+ )
+
+ job = await root.client.jobs.submit(
+ image=image_obj,
+ resources=resources,
+ network=network,
+ volumes=list(volumes) if volumes else None,
+ is_preemptible=preemptible,
+ name=name,
+ description=description,
+ env=env_dict,
+ )
+ click.echo(JobFormatter(quiet)(job))
+ progress = JobStartProgress.create(tty=root.tty, color=root.color, quiet=quiet)
+ while wait_start and job.status == JobStatus.PENDING:
+ await asyncio.sleep(0.2)
+ job = await root.client.jobs.status(job.id)
+ progress(job)
+ progress.close()
diff --git a/neuromation/cli/main.py b/neuromation/cli/main.py
index 4b4beeb27..942482d49 100644
--- a/neuromation/cli/main.py
+++ b/neuromation/cli/main.py
@@ -207,6 +207,7 @@ def help(ctx: click.Context, command: Sequence[str]) -> None:
ctx.close()
+# groups
cli.add_command(job.job)
cli.add_command(storage.storage)
cli.add_command(image.image)
@@ -215,6 +216,8 @@ def help(ctx: click.Context, command: Sequence[str]) -> None:
cli.add_command(DeprecatedGroup(storage.storage, name="store", hidden=True))
+# shortcuts
+cli.add_command(job.run)
cli.add_command(job.submit)
cli.add_command(alias(job.ls, "ps", help=job.ls.help, deprecated=False))
cli.add_command(job.status)
diff --git a/python/README.md b/python/README.md
new file mode 100644
index 000000000..06036fedb
--- /dev/null
+++ b/python/README.md
@@ -0,0 +1,1444 @@
+[![codecov](https://codecov.io/gh/neuromation/platform-api-clients/branch/master/graph/badge.svg?token=FwM6ZV3gDj)](https://codecov.io/gh/neuromation/platform-api-clients)
+
+# Table of Contents
+* [Preface](#Preface)
+* [neuro](#neuro)
+ * [neuro job](#neuro-job)
+ * [neuro job run](#neuro-job-run)
+ * [neuro job submit](#neuro-job-submit)
+ * [neuro job ls](#neuro-job-ls)
+ * [neuro job status](#neuro-job-status)
+ * [neuro job exec](#neuro-job-exec)
+ * [neuro job port-forward](#neuro-job-port-forward)
+ * [neuro job logs](#neuro-job-logs)
+ * [neuro job kill](#neuro-job-kill)
+ * [neuro job top](#neuro-job-top)
+ * [neuro storage](#neuro-storage)
+ * [neuro storage cp](#neuro-storage-cp)
+ * [neuro storage ls](#neuro-storage-ls)
+ * [neuro storage rm](#neuro-storage-rm)
+ * [neuro storage mkdir](#neuro-storage-mkdir)
+ * [neuro storage mv](#neuro-storage-mv)
+ * [neuro image](#neuro-image)
+ * [neuro image ls](#neuro-image-ls)
+ * [neuro image push](#neuro-image-push)
+ * [neuro image pull](#neuro-image-pull)
+ * [neuro config](#neuro-config)
+ * [neuro config login](#neuro-config-login)
+ * [neuro config show](#neuro-config-show)
+ * [neuro config show-token](#neuro-config-show-token)
+ * [neuro config auth](#neuro-config-auth)
+ * [neuro config logout](#neuro-config-logout)
+ * [neuro completion](#neuro-completion)
+ * [neuro completion generate](#neuro-completion-generate)
+ * [neuro completion patch](#neuro-completion-patch)
+ * [neuro help](#neuro-help)
+ * [neuro run](#neuro-run)
+ * [neuro submit](#neuro-submit)
+ * [neuro ps](#neuro-ps)
+ * [neuro status](#neuro-status)
+ * [neuro exec](#neuro-exec)
+ * [neuro port-forward](#neuro-port-forward)
+ * [neuro logs](#neuro-logs)
+ * [neuro kill](#neuro-kill)
+ * [neuro top](#neuro-top)
+ * [neuro login](#neuro-login)
+ * [neuro logout](#neuro-logout)
+ * [neuro cp](#neuro-cp)
+ * [neuro ls](#neuro-ls)
+ * [neuro rm](#neuro-rm)
+ * [neuro mkdir](#neuro-mkdir)
+ * [neuro mv](#neuro-mv)
+ * [neuro images](#neuro-images)
+ * [neuro push](#neuro-push)
+ * [neuro pull](#neuro-pull)
+ * [neuro share](#neuro-share)
+* [Api](#Api)
+* [Contributing](#Contributing)
+
+
+# Preface
+
+Welcome to Neuromation API Python client.
+Package ship command line tool called [_neuro_](#neuro). With [_neuro_](#neuro) you can:
+* [Execute and debug jobs](#neuro-job)
+* [Manipulate Data](#neuro-storage)
+* Make some fun
+
+# neuro
+
+**Usage:**
+
+```bash
+neuro [OPTIONS] COMMAND [ARGS]...
+```
+
+**Options:**
+
+Name | Description|
+|----|------------|
+|_\-v, --verbose_|Enable verbose mode.|
+|_\--show-traceback_|Show python traceback on error, useful for debugging the tool.|
+|_--color \[yes | no | auto]_|Color mode.|
+|_\--disable-pypi-version-check_|Don't periodically check PyPI to determine whether a new version of Neuromation CLI is available for download.|
+|_\--network-timeout FLOAT_|Network read timeout, seconds.|
+|_--version_|Show the version and exit.|
+|_--help_|Show this message and exit.|
+
+
+**Command Groups:**
+
+|Usage|Description|
+|---|---|
+| _[neuro job](#neuro-job)_| Job operations |
+| _[neuro storage](#neuro-storage)_| Storage operations |
+| _[neuro image](#neuro-image)_| Container image operations |
+| _[neuro config](#neuro-config)_| Client configuration |
+| _[neuro completion](#neuro-completion)_| Output shell completion code |
+
+
+**Commands:**
+
+|Usage|Description|
+|---|---|
+| _[neuro help](#neuro-help)_| Get help on a command |
+| _[neuro run](#neuro-run)_| Run an image with predefined configuration |
+| _[neuro submit](#neuro-submit)_| Submit an image to run on the cluster |
+| _[neuro ps](#neuro-ps)_| List all jobs |
+| _[neuro status](#neuro-status)_| Display status of a job |
+| _[neuro exec](#neuro-exec)_| Execute command in a running job |
+| _[neuro port-forward](#neuro-port-forward)_| Forward a port of a running job exposed with -ssh option to a local port |
+| _[neuro logs](#neuro-logs)_| Print the logs for a container |
+| _[neuro kill](#neuro-kill)_| Kill job\(s) |
+| _[neuro top](#neuro-top)_| Display GPU/CPU/Memory usage |
+| _[neuro login](#neuro-login)_| Log into Neuromation Platform |
+| _[neuro logout](#neuro-logout)_| Log out |
+| _[neuro cp](#neuro-cp)_| Copy files and directories |
+| _[neuro ls](#neuro-ls)_| List directory contents |
+| _[neuro rm](#neuro-rm)_| Remove files or directories |
+| _[neuro mkdir](#neuro-mkdir)_| Make directories |
+| _[neuro mv](#neuro-mv)_| Move or rename files and directories |
+| _[neuro images](#neuro-images)_| List images |
+| _[neuro push](#neuro-push)_| Push an image to platform registry |
+| _[neuro pull](#neuro-pull)_| Pull an image from platform registry |
+| _[neuro share](#neuro-share)_| Shares resource specified by URI to a USER with PERMISSION Examples: neuro share... |
+
+
+
+
+## neuro job
+
+Job operations.
+
+**Usage:**
+
+```bash
+neuro job [OPTIONS] COMMAND [ARGS]...
+```
+
+**Options:**
+
+Name | Description|
+|----|------------|
+|_--help_|Show this message and exit.|
+
+
+**Commands:**
+
+|Usage|Description|
+|---|---|
+| _[neuro job run](#neuro-job-run)_| Run an image with predefined configuration |
+| _[neuro job submit](#neuro-job-submit)_| Submit an image to run on the cluster |
+| _[neuro job ls](#neuro-job-ls)_| List all jobs |
+| _[neuro job status](#neuro-job-status)_| Display status of a job |
+| _[neuro job exec](#neuro-job-exec)_| Execute command in a running job |
+| _[neuro job port-forward](#neuro-job-port-forward)_| Forward a port of a running job exposed with -ssh option to a local port |
+| _[neuro job logs](#neuro-job-logs)_| Print the logs for a container |
+| _[neuro job kill](#neuro-job-kill)_| Kill job\(s) |
+| _[neuro job top](#neuro-job-top)_| Display GPU/CPU/Memory usage |
+
+
+
+
+### neuro job run
+
+Run an image with predefined configuration.
IMAGE container image name.
CMD list will be passed as commands to model container.
+
+**Usage:**
+
+```bash
+neuro job run [OPTIONS] IMAGE [CMD]...
+```
+
+**Examples:**
+
+```bash
+
+# Starts a container pytorch:latest with two paths mounted. Directory /q1/
+# is mounted in read only mode to /qm directory within container.
+# Directory /mod mounted to /mod directory in read-write mode.
+neuro run pytorch:latest
+
+# Starts a container pytorch:latest with connection enabled to port 22 and
+# sets PYTHONPATH environment value to /python.
+# Please note that SSH server should be provided by container.
+neuro run --env PYTHONPATH=/python --ssh 22 pytorch:latest
+
+```
+
+**Options:**
+
+Name | Description|
+|----|------------|
+|_\-s, --preset PRESET_|Predefined job profile \[default: gpu-small]|
+|_\-x, --extshm / -X, --no-extshm_|Request extended '/dev/shm' space \[default: True]|
+|_--http INTEGER_|Enable HTTP port forwarding to container \[default: 80]|
+|_\--http-auth / --no-http-auth_|Enable HTTP authentication for forwarded HTTP port \[default: True]|
+|_--ssh INTEGER_|Enable SSH port forwarding to container|
+|_\-p, --preemptible / -P, --non-preemptible_|Run job on a lower-cost preemptible instance \[default: True]|
+|_\-d, --description DESC_|Add optional description to the job|
+|_\-q, --quiet_|Run command in quiet mode \(print only job id)|
+|_\-e, --env VAR=VAL_|Set environment variable in container Use multiple options to define more than one variable|
+|_\--env-file PATH_|File with environment variables to pass|
+|_\--wait-start / --no-wait-start_|Wait for a job start or failure \[default: True]|
+|_--help_|Show this message and exit.|
+
+
+
+
+### neuro job submit
+
+Submit an image to run on the cluster.
IMAGE container image name.
CMD list will be passed as commands to model container.
+
+**Usage:**
+
+```bash
+neuro job submit [OPTIONS] IMAGE [CMD]...
+```
+
+**Examples:**
+
+```bash
+
+# Starts a container pytorch:latest with two paths mounted. Directory /q1/
+# is mounted in read only mode to /qm directory within container.
+# Directory /mod mounted to /mod directory in read-write mode.
+neuro job submit --volume storage:/q1:/qm:ro --volume storage:/mod:/mod:rw pytorch:latest
+
+# Starts a container pytorch:latest with connection enabled to port 22 and
+# sets PYTHONPATH environment value to /python.
+# Please note that SSH server should be provided by container.
+neuro job submit --env PYTHONPATH=/python --volume storage:/data/2018q1:/data:ro --ssh 22 pytorch:latest
+
+```
+
+**Options:**
+
+Name | Description|
+|----|------------|
+|_\-g, --gpu NUMBER_|Number of GPUs to request \[default: 0]|
+|_\--gpu-model MODEL_|GPU to use \[default: nvidia\-tesla-k80]|
+|_\-c, --cpu NUMBER_|Number of CPUs to request \[default: 0.1]|
+|_\-m, --memory AMOUNT_|Memory amount to request \[default: 1G]|
+|_\-x, --extshm / -X, --no-extshm_|Request extended '/dev/shm' space \[default: True]|
+|_--http INTEGER_|Enable HTTP port forwarding to container|
+|_\--http-auth / --no-http-auth_|Enable HTTP authentication for forwarded HTTP port \[default: True]|
+|_--ssh INTEGER_|Enable SSH port forwarding to container|
+|_\-p, --preemptible / -P, --non-preemptible_|Run job on a lower-cost preemptible instance \[default: True]|
+|_\-n, --name NAME_|Optional job name|
+|_\-d, --description DESC_|Optional job description in free format|
+|_\-q, --quiet_|Run command in quiet mode \(print only job id)|
+|_\-v, --volume MOUNT_|Mounts directory from vault into container. Use multiple options to mount more than one volume|
+|_\-e, --env VAR=VAL_|Set environment variable in container Use multiple options to define more than one variable|
+|_\--env-file PATH_|File with environment variables to pass|
+|_\--wait-start / --no-wait-start_|Wait for a job start or failure \[default: True]|
+|_--help_|Show this message and exit.|
+
+
+
+
+### neuro job ls
+
+List all jobs.
+
+**Usage:**
+
+```bash
+neuro job ls [OPTIONS]
+```
+
+**Examples:**
+
+```bash
+
+neuro job ls --description=my favourite job
+neuro job ls --status=all
+neuro job ls -s pending -s running -q
+
+```
+
+**Options:**
+
+Name | Description|
+|----|------------|
+|_\-s, --status \[pending | running | succeeded | failed | all]_|Filter out job by status \(multiple option)|
+|_\-d, --description DESCRIPTION_|Filter out job by job description \(exact match)|
+|_\-q, --quiet_|Print only Job ID|
+|_\-w, --wide_|Do not cut long lines for terminal width|
+|_--help_|Show this message and exit.|
+
+
+
+
+### neuro job status
+
+Display status of a job.
+
+**Usage:**
+
+```bash
+neuro job status [OPTIONS] ID
+```
+
+**Options:**
+
+Name | Description|
+|----|------------|
+|_--help_|Show this message and exit.|
+
+
+
+
+### neuro job exec
+
+Execute command in a running job.
+
+**Usage:**
+
+```bash
+neuro job exec [OPTIONS] ID CMD...
+```
+
+**Options:**
+
+Name | Description|
+|----|------------|
+|_\-t, --tty_|Allocate virtual tty. Useful for interactive jobs.|
+|_\--no-key-check_|Disable host key checks. Should be used with caution.|
+|_--help_|Show this message and exit.|
+
+
+
+
+### neuro job port-forward
+
+Forward a port of a running job exposed with -ssh option to a local port.
+
+**Usage:**
+
+```bash
+neuro job port-forward [OPTIONS] ID LOCAL_PORT REMOTE_PORT
+```
+
+**Options:**
+
+Name | Description|
+|----|------------|
+|_\--no-key-check_|Disable host key checks. Should be used with caution.|
+|_--help_|Show this message and exit.|
+
+
+
+
+### neuro job logs
+
+Print the logs for a container.
+
+**Usage:**
+
+```bash
+neuro job logs [OPTIONS] ID
+```
+
+**Options:**
+
+Name | Description|
+|----|------------|
+|_--help_|Show this message and exit.|
+
+
+
+
+### neuro job kill
+
+Kill job\(s).
+
+**Usage:**
+
+```bash
+neuro job kill [OPTIONS] ID...
+```
+
+**Options:**
+
+Name | Description|
+|----|------------|
+|_--help_|Show this message and exit.|
+
+
+
+
+### neuro job top
+
+Display GPU/CPU/Memory usage.
+
+**Usage:**
+
+```bash
+neuro job top [OPTIONS] ID
+```
+
+**Options:**
+
+Name | Description|
+|----|------------|
+|_--help_|Show this message and exit.|
+
+
+
+
+## neuro storage
+
+Storage operations.
+
+**Usage:**
+
+```bash
+neuro storage [OPTIONS] COMMAND [ARGS]...
+```
+
+**Options:**
+
+Name | Description|
+|----|------------|
+|_--help_|Show this message and exit.|
+
+
+**Commands:**
+
+|Usage|Description|
+|---|---|
+| _[neuro storage cp](#neuro-storage-cp)_| Copy files and directories |
+| _[neuro storage ls](#neuro-storage-ls)_| List directory contents |
+| _[neuro storage rm](#neuro-storage-rm)_| Remove files or directories |
+| _[neuro storage mkdir](#neuro-storage-mkdir)_| Make directories |
+| _[neuro storage mv](#neuro-storage-mv)_| Move or rename files and directories |
+
+
+
+
+### neuro storage cp
+
+Copy files and directories.
Either SOURCE or DESTINATION should have storage:// scheme. If scheme is
omitted, file:// scheme is assumed.
+
+**Usage:**
+
+```bash
+neuro storage cp [OPTIONS] SOURCE DESTINATION
+```
+
+**Examples:**
+
+```bash
+
+# copy local file ./foo into remote storage root
+neuro storage cp ./foo storage:///
+neuro storage cp ./foo storage:/
+
+# download remote file foo into local file foo with
+# explicit file:// scheme set
+neuro storage cp storage:///foo file:///foo
+
+```
+
+**Options:**
+
+Name | Description|
+|----|------------|
+|_\-r, --recursive_|Recursive copy, off by default|
+|_\-p, --progress_|Show progress, off by default|
+|_--help_|Show this message and exit.|
+
+
+
+
+### neuro storage ls
+
+List directory contents.
By default PATH is equal user`s home dir \(storage:)
+
+**Usage:**
+
+```bash
+neuro storage ls [OPTIONS] [PATH]
+```
+
+**Options:**
+
+Name | Description|
+|----|------------|
+|_\-h, --human-readable_|with -l print human readable sizes \(e.g., 2K, 540M)|
+|_-l_|use a long listing format|
+|_--sort \[name | size | time]_|sort by given field, default is name|
+|_--help_|Show this message and exit.|
+
+
+
+
+### neuro storage rm
+
+Remove files or directories.
+
+**Usage:**
+
+```bash
+neuro storage rm [OPTIONS] PATH
+```
+
+**Examples:**
+
+```bash
+
+neuro storage rm storage:///foo/bar/
+neuro storage rm storage:/foo/bar/
+neuro storage rm storage://{username}/foo/bar/
+
+```
+
+**Options:**
+
+Name | Description|
+|----|------------|
+|_--help_|Show this message and exit.|
+
+
+
+
+### neuro storage mkdir
+
+Make directories.
+
+**Usage:**
+
+```bash
+neuro storage mkdir [OPTIONS] PATH
+```
+
+**Options:**
+
+Name | Description|
+|----|------------|
+|_--help_|Show this message and exit.|
+
+
+
+
+### neuro storage mv
+
+Move or rename files and directories.
SOURCE must contain path to the file or directory existing on the storage,
and DESTINATION must contain the full path to the target file or directory.
+
+**Usage:**
+
+```bash
+neuro storage mv [OPTIONS] SOURCE DESTINATION
+```
+
+**Examples:**
+
+```bash
+
+# move or rename remote file
+neuro storage mv storage://{username}/foo.txt storage://{username}/bar.txt
+neuro storage mv storage://{username}/foo.txt storage://~/bar/baz/foo.txt
+
+# move or rename remote directory
+neuro storage mv storage://{username}/foo/ storage://{username}/bar/
+neuro storage mv storage://{username}/foo/ storage://{username}/bar/baz/foo/
+
+```
+
+**Options:**
+
+Name | Description|
+|----|------------|
+|_--help_|Show this message and exit.|
+
+
+
+
+## neuro image
+
+Container image operations.
+
+**Usage:**
+
+```bash
+neuro image [OPTIONS] COMMAND [ARGS]...
+```
+
+**Options:**
+
+Name | Description|
+|----|------------|
+|_--help_|Show this message and exit.|
+
+
+**Commands:**
+
+|Usage|Description|
+|---|---|
+| _[neuro image ls](#neuro-image-ls)_| List images |
+| _[neuro image push](#neuro-image-push)_| Push an image to platform registry |
+| _[neuro image pull](#neuro-image-pull)_| Pull an image from platform registry |
+
+
+
+
+### neuro image ls
+
+List images.
+
+**Usage:**
+
+```bash
+neuro image ls [OPTIONS]
+```
+
+**Options:**
+
+Name | Description|
+|----|------------|
+|_--help_|Show this message and exit.|
+
+
+
+
+### neuro image push
+
+Push an image to platform registry.
Remote image must be URL with image:// scheme. Image names can contains tag.
If tags not specified 'latest' will be used as value.
+
+**Usage:**
+
+```bash
+neuro image push [OPTIONS] IMAGE_NAME [REMOTE_IMAGE_NAME]
+```
+
+**Examples:**
+
+```bash
+
+neuro image push myimage
+neuro image push alpine:latest image:my-alpine:production
+neuro image push alpine image://myfriend/alpine:shared
+
+```
+
+**Options:**
+
+Name | Description|
+|----|------------|
+|_--help_|Show this message and exit.|
+
+
+
+
+### neuro image pull
+
+Pull an image from platform registry.
Remote image name must be URL with image:// scheme. Image names can contain
tag.
+
+**Usage:**
+
+```bash
+neuro image pull [OPTIONS] IMAGE_NAME [LOCAL_IMAGE_NAME]
+```
+
+**Examples:**
+
+```bash
+
+neuro image pull image:myimage
+neuro image pull image://myfriend/alpine:shared
+neuro image pull image://username/my-alpine:production alpine:from-registry
+
+```
+
+**Options:**
+
+Name | Description|
+|----|------------|
+|_--help_|Show this message and exit.|
+
+
+
+
+## neuro config
+
+Client configuration.
+
+**Usage:**
+
+```bash
+neuro config [OPTIONS] COMMAND [ARGS]...
+```
+
+**Options:**
+
+Name | Description|
+|----|------------|
+|_--help_|Show this message and exit.|
+
+
+**Commands:**
+
+|Usage|Description|
+|---|---|
+| _[neuro config login](#neuro-config-login)_| Log into Neuromation Platform |
+| _[neuro config show](#neuro-config-show)_| Print current settings |
+| _[neuro config show-token](#neuro-config-show-token)_| Print current authorization token |
+| _[neuro config auth](#neuro-config-auth)_| Update authorization token |
+| _[neuro config logout](#neuro-config-logout)_| Log out |
+
+
+
+
+### neuro config login
+
+Log into Neuromation Platform.
+
+**Usage:**
+
+```bash
+neuro config login [OPTIONS] [URL]
+```
+
+**Options:**
+
+Name | Description|
+|----|------------|
+|_--help_|Show this message and exit.|
+
+
+
+
+### neuro config show
+
+Print current settings.
+
+**Usage:**
+
+```bash
+neuro config show [OPTIONS]
+```
+
+**Options:**
+
+Name | Description|
+|----|------------|
+|_--help_|Show this message and exit.|
+
+
+
+
+### neuro config show-token
+
+Print current authorization token.
+
+**Usage:**
+
+```bash
+neuro config show-token [OPTIONS]
+```
+
+**Options:**
+
+Name | Description|
+|----|------------|
+|_--help_|Show this message and exit.|
+
+
+
+
+### neuro config auth
+
+Update authorization token.
+
+**Usage:**
+
+```bash
+neuro config auth [OPTIONS] TOKEN
+```
+
+**Options:**
+
+Name | Description|
+|----|------------|
+|_--help_|Show this message and exit.|
+
+
+
+
+### neuro config logout
+
+Log out.
+
+**Usage:**
+
+```bash
+neuro config logout [OPTIONS]
+```
+
+**Options:**
+
+Name | Description|
+|----|------------|
+|_--help_|Show this message and exit.|
+
+
+
+
+## neuro completion
+
+Output shell completion code.
+
+**Usage:**
+
+```bash
+neuro completion [OPTIONS] COMMAND [ARGS]...
+```
+
+**Options:**
+
+Name | Description|
+|----|------------|
+|_--help_|Show this message and exit.|
+
+
+**Commands:**
+
+|Usage|Description|
+|---|---|
+| _[neuro completion generate](#neuro-completion-generate)_| Provide an instruction for shell completion generation |
+| _[neuro completion patch](#neuro-completion-patch)_| Automatically patch shell configuration profile to enable completion |
+
+
+
+
+### neuro completion generate
+
+Provide an instruction for shell completion generation.
+
+**Usage:**
+
+```bash
+neuro completion generate [OPTIONS] [bash|zsh]
+```
+
+**Options:**
+
+Name | Description|
+|----|------------|
+|_--help_|Show this message and exit.|
+
+
+
+
+### neuro completion patch
+
+Automatically patch shell configuration profile to enable completion
+
+**Usage:**
+
+```bash
+neuro completion patch [OPTIONS] [bash|zsh]
+```
+
+**Options:**
+
+Name | Description|
+|----|------------|
+|_--help_|Show this message and exit.|
+
+
+
+
+## neuro help
+
+Get help on a command.
+
+**Usage:**
+
+```bash
+neuro help [OPTIONS] [COMMAND]...
+```
+
+**Options:**
+
+Name | Description|
+|----|------------|
+|_--help_|Show this message and exit.|
+
+
+
+
+## neuro run
+
+Run an image with predefined configuration.
IMAGE container image name.
CMD list will be passed as commands to model container.
+
+**Usage:**
+
+```bash
+neuro run [OPTIONS] IMAGE [CMD]...
+```
+
+**Examples:**
+
+```bash
+
+# Starts a container pytorch:latest with two paths mounted. Directory /q1/
+# is mounted in read only mode to /qm directory within container.
+# Directory /mod mounted to /mod directory in read-write mode.
+neuro run pytorch:latest
+
+# Starts a container pytorch:latest with connection enabled to port 22 and
+# sets PYTHONPATH environment value to /python.
+# Please note that SSH server should be provided by container.
+neuro run --env PYTHONPATH=/python --ssh 22 pytorch:latest
+
+```
+
+**Options:**
+
+Name | Description|
+|----|------------|
+|_\-s, --preset PRESET_|Predefined job profile \[default: gpu-small]|
+|_\-x, --extshm / -X, --no-extshm_|Request extended '/dev/shm' space \[default: True]|
+|_--http INTEGER_|Enable HTTP port forwarding to container \[default: 80]|
+|_\--http-auth / --no-http-auth_|Enable HTTP authentication for forwarded HTTP port \[default: True]|
+|_--ssh INTEGER_|Enable SSH port forwarding to container|
+|_\-p, --preemptible / -P, --non-preemptible_|Run job on a lower-cost preemptible instance \[default: True]|
+|_\-d, --description DESC_|Add optional description to the job|
+|_\-q, --quiet_|Run command in quiet mode \(print only job id)|
+|_\-e, --env VAR=VAL_|Set environment variable in container Use multiple options to define more than one variable|
+|_\--env-file PATH_|File with environment variables to pass|
+|_\--wait-start / --no-wait-start_|Wait for a job start or failure \[default: True]|
+|_--help_|Show this message and exit.|
+
+
+
+
+## neuro submit
+
+Submit an image to run on the cluster.
IMAGE container image name.
CMD list will be passed as commands to model container.
+
+**Usage:**
+
+```bash
+neuro submit [OPTIONS] IMAGE [CMD]...
+```
+
+**Examples:**
+
+```bash
+
+# Starts a container pytorch:latest with two paths mounted. Directory /q1/
+# is mounted in read only mode to /qm directory within container.
+# Directory /mod mounted to /mod directory in read-write mode.
+neuro job submit --volume storage:/q1:/qm:ro --volume storage:/mod:/mod:rw pytorch:latest
+
+# Starts a container pytorch:latest with connection enabled to port 22 and
+# sets PYTHONPATH environment value to /python.
+# Please note that SSH server should be provided by container.
+neuro job submit --env PYTHONPATH=/python --volume storage:/data/2018q1:/data:ro --ssh 22 pytorch:latest
+
+```
+
+**Options:**
+
+Name | Description|
+|----|------------|
+|_\-g, --gpu NUMBER_|Number of GPUs to request \[default: 0]|
+|_\--gpu-model MODEL_|GPU to use \[default: nvidia\-tesla-k80]|
+|_\-c, --cpu NUMBER_|Number of CPUs to request \[default: 0.1]|
+|_\-m, --memory AMOUNT_|Memory amount to request \[default: 1G]|
+|_\-x, --extshm / -X, --no-extshm_|Request extended '/dev/shm' space \[default: True]|
+|_--http INTEGER_|Enable HTTP port forwarding to container|
+|_\--http-auth / --no-http-auth_|Enable HTTP authentication for forwarded HTTP port \[default: True]|
+|_--ssh INTEGER_|Enable SSH port forwarding to container|
+|_\-p, --preemptible / -P, --non-preemptible_|Run job on a lower-cost preemptible instance \[default: True]|
+|_\-n, --name NAME_|Optional job name|
+|_\-d, --description DESC_|Optional job description in free format|
+|_\-q, --quiet_|Run command in quiet mode \(print only job id)|
+|_\-v, --volume MOUNT_|Mounts directory from vault into container. Use multiple options to mount more than one volume|
+|_\-e, --env VAR=VAL_|Set environment variable in container Use multiple options to define more than one variable|
+|_\--env-file PATH_|File with environment variables to pass|
+|_\--wait-start / --no-wait-start_|Wait for a job start or failure \[default: True]|
+|_--help_|Show this message and exit.|
+
+
+
+
+## neuro ps
+
+List all jobs.
+
+**Usage:**
+
+```bash
+neuro ps [OPTIONS]
+```
+
+**Examples:**
+
+```bash
+
+neuro job ls --description=my favourite job
+neuro job ls --status=all
+neuro job ls -s pending -s running -q
+
+```
+
+**Options:**
+
+Name | Description|
+|----|------------|
+|_\-s, --status \[pending | running | succeeded | failed | all]_|Filter out job by status \(multiple option)|
+|_\-d, --description DESCRIPTION_|Filter out job by job description \(exact match)|
+|_\-q, --quiet_|Print only Job ID|
+|_\-w, --wide_|Do not cut long lines for terminal width|
+|_--help_|Show this message and exit.|
+
+
+
+
+## neuro status
+
+Display status of a job.
+
+**Usage:**
+
+```bash
+neuro status [OPTIONS] ID
+```
+
+**Options:**
+
+Name | Description|
+|----|------------|
+|_--help_|Show this message and exit.|
+
+
+
+
+## neuro exec
+
+Execute command in a running job.
+
+**Usage:**
+
+```bash
+neuro exec [OPTIONS] ID CMD...
+```
+
+**Options:**
+
+Name | Description|
+|----|------------|
+|_\-t, --tty_|Allocate virtual tty. Useful for interactive jobs.|
+|_\--no-key-check_|Disable host key checks. Should be used with caution.|
+|_--help_|Show this message and exit.|
+
+
+
+
+## neuro port-forward
+
+Forward a port of a running job exposed with -ssh option to a local port.
+
+**Usage:**
+
+```bash
+neuro port-forward [OPTIONS] ID LOCAL_PORT REMOTE_PORT
+```
+
+**Options:**
+
+Name | Description|
+|----|------------|
+|_\--no-key-check_|Disable host key checks. Should be used with caution.|
+|_--help_|Show this message and exit.|
+
+
+
+
+## neuro logs
+
+Print the logs for a container.
+
+**Usage:**
+
+```bash
+neuro logs [OPTIONS] ID
+```
+
+**Options:**
+
+Name | Description|
+|----|------------|
+|_--help_|Show this message and exit.|
+
+
+
+
+## neuro kill
+
+Kill job\(s).
+
+**Usage:**
+
+```bash
+neuro kill [OPTIONS] ID...
+```
+
+**Options:**
+
+Name | Description|
+|----|------------|
+|_--help_|Show this message and exit.|
+
+
+
+
+## neuro top
+
+Display GPU/CPU/Memory usage.
+
+**Usage:**
+
+```bash
+neuro top [OPTIONS] ID
+```
+
+**Options:**
+
+Name | Description|
+|----|------------|
+|_--help_|Show this message and exit.|
+
+
+
+
+## neuro login
+
+Log into Neuromation Platform.
+
+**Usage:**
+
+```bash
+neuro login [OPTIONS] [URL]
+```
+
+**Options:**
+
+Name | Description|
+|----|------------|
+|_--help_|Show this message and exit.|
+
+
+
+
+## neuro logout
+
+Log out.
+
+**Usage:**
+
+```bash
+neuro logout [OPTIONS]
+```
+
+**Options:**
+
+Name | Description|
+|----|------------|
+|_--help_|Show this message and exit.|
+
+
+
+
+## neuro cp
+
+Copy files and directories.
Either SOURCE or DESTINATION should have storage:// scheme. If scheme is
omitted, file:// scheme is assumed.
+
+**Usage:**
+
+```bash
+neuro cp [OPTIONS] SOURCE DESTINATION
+```
+
+**Examples:**
+
+```bash
+
+# copy local file ./foo into remote storage root
+neuro storage cp ./foo storage:///
+neuro storage cp ./foo storage:/
+
+# download remote file foo into local file foo with
+# explicit file:// scheme set
+neuro storage cp storage:///foo file:///foo
+
+```
+
+**Options:**
+
+Name | Description|
+|----|------------|
+|_\-r, --recursive_|Recursive copy, off by default|
+|_\-p, --progress_|Show progress, off by default|
+|_--help_|Show this message and exit.|
+
+
+
+
+## neuro ls
+
+List directory contents.
By default PATH is equal user`s home dir \(storage:)
+
+**Usage:**
+
+```bash
+neuro ls [OPTIONS] [PATH]
+```
+
+**Options:**
+
+Name | Description|
+|----|------------|
+|_\-h, --human-readable_|with -l print human readable sizes \(e.g., 2K, 540M)|
+|_-l_|use a long listing format|
+|_--sort \[name | size | time]_|sort by given field, default is name|
+|_--help_|Show this message and exit.|
+
+
+
+
+## neuro rm
+
+Remove files or directories.
+
+**Usage:**
+
+```bash
+neuro rm [OPTIONS] PATH
+```
+
+**Examples:**
+
+```bash
+
+neuro storage rm storage:///foo/bar/
+neuro storage rm storage:/foo/bar/
+neuro storage rm storage://{username}/foo/bar/
+
+```
+
+**Options:**
+
+Name | Description|
+|----|------------|
+|_--help_|Show this message and exit.|
+
+
+
+
+## neuro mkdir
+
+Make directories.
+
+**Usage:**
+
+```bash
+neuro mkdir [OPTIONS] PATH
+```
+
+**Options:**
+
+Name | Description|
+|----|------------|
+|_--help_|Show this message and exit.|
+
+
+
+
+## neuro mv
+
+Move or rename files and directories.
SOURCE must contain path to the file or directory existing on the storage,
and DESTINATION must contain the full path to the target file or directory.
+
+**Usage:**
+
+```bash
+neuro mv [OPTIONS] SOURCE DESTINATION
+```
+
+**Examples:**
+
+```bash
+
+# move or rename remote file
+neuro storage mv storage://{username}/foo.txt storage://{username}/bar.txt
+neuro storage mv storage://{username}/foo.txt storage://~/bar/baz/foo.txt
+
+# move or rename remote directory
+neuro storage mv storage://{username}/foo/ storage://{username}/bar/
+neuro storage mv storage://{username}/foo/ storage://{username}/bar/baz/foo/
+
+```
+
+**Options:**
+
+Name | Description|
+|----|------------|
+|_--help_|Show this message and exit.|
+
+
+
+
+## neuro images
+
+List images.
+
+**Usage:**
+
+```bash
+neuro images [OPTIONS]
+```
+
+**Options:**
+
+Name | Description|
+|----|------------|
+|_--help_|Show this message and exit.|
+
+
+
+
+## neuro push
+
+Push an image to platform registry.
Remote image must be URL with image:// scheme. Image names can contains tag.
If tags not specified 'latest' will be used as value.
+
+**Usage:**
+
+```bash
+neuro push [OPTIONS] IMAGE_NAME [REMOTE_IMAGE_NAME]
+```
+
+**Examples:**
+
+```bash
+
+neuro image push myimage
+neuro image push alpine:latest image:my-alpine:production
+neuro image push alpine image://myfriend/alpine:shared
+
+```
+
+**Options:**
+
+Name | Description|
+|----|------------|
+|_--help_|Show this message and exit.|
+
+
+
+
+## neuro pull
+
+Pull an image from platform registry.
Remote image name must be URL with image:// scheme. Image names can contain
tag.
+
+**Usage:**
+
+```bash
+neuro pull [OPTIONS] IMAGE_NAME [LOCAL_IMAGE_NAME]
+```
+
+**Examples:**
+
+```bash
+
+neuro image pull image:myimage
+neuro image pull image://myfriend/alpine:shared
+neuro image pull image://username/my-alpine:production alpine:from-registry
+
+```
+
+**Options:**
+
+Name | Description|
+|----|------------|
+|_--help_|Show this message and exit.|
+
+
+
+
+## neuro share
+
+Shares resource specified by URI to a USER with PERMISSION
+
+**Usage:**
+
+```bash
+neuro share [OPTIONS] URI USER [read|write|manage]
+```
+
+**Examples:**
+
+```bash
+
+neuro share storage:///sample_data/ alice manage
+neuro share image:resnet50 bob read
+neuro share job:///my_job_id alice write
+
+```
+
+**Options:**
+
+Name | Description|
+|----|------------|
+|_--help_|Show this message and exit.|
+
+
+
+
+# Api
+
+*TODO*
+
+# Contributing
+
+```shell
+git clone https://github.com/neuromation/platform-api-clients.git
+cd platform-api-clients/python
+```
+
+Before you begin, it is recommended to have clean virtual environment installed:
+
+```shell
+python -m venv .env
+source .env/bin/activate
+```
+
+Development flow:
+
+* Install dependencies: `make init`
+* Run tests: `make test`
+* Lint: `make lint`
+* Publish to [pypi](https://pypi.org/project/neuromation/): `make publish`
\ No newline at end of file
diff --git a/tests/e2e/conftest.py b/tests/e2e/conftest.py
index a94877ed5..0b144810c 100644
--- a/tests/e2e/conftest.py
+++ b/tests/e2e/conftest.py
@@ -418,7 +418,7 @@ def run_cli(self, arguments: List[str], storage_retry: bool = True) -> SysCap:
err = post_err[pre_err_size:]
if any(
" ".join(arguments).startswith(start)
- for start in ("submit", "job submit")
+ for start in ("submit", "job submit", "run", "job run")
):
match = job_id_pattern.search(out)
if match:
diff --git a/tests/e2e/test_e2e_jobs.py b/tests/e2e/test_e2e_jobs.py
index 5a89fb345..e224c5a72 100644
--- a/tests/e2e/test_e2e_jobs.py
+++ b/tests/e2e/test_e2e_jobs.py
@@ -711,3 +711,34 @@ async def _test_http_auth_with_cookie(url, cookies, secret):
run_async(
_test_http_auth_with_cookie(ingress_secret_url, cookies, http_job["secret"])
)
+
+
+@pytest.mark.e2e
+def test_job_run(helper):
+ # Run a new job
+ command = 'bash -c "sleep 10m; false"'
+ captured = helper.run_cli(
+ [
+ "job",
+ "run",
+ "-q",
+ "-s",
+ "cpu-small",
+ "--non-preemptible",
+ "--no-wait-start",
+ UBUNTU_IMAGE_NAME,
+ command,
+ ]
+ )
+ job_id = captured.out
+
+ # Wait until the job is running
+ helper.wait_job_change_state_to(job_id, JobStatus.RUNNING)
+
+ # Kill the job
+ captured = helper.run_cli(["job", "kill", job_id])
+
+ # Currently we check that the job is not running anymore
+ # TODO(adavydow): replace to succeeded check when racecon in
+ # platform-api fixed.
+ helper.wait_job_change_state_from(job_id, JobStatus.RUNNING)