Skip to content
This repository has been archived by the owner on May 30, 2021. It is now read-only.

Commit

Permalink
Release 0.5.0 (#49)
Browse files Browse the repository at this point in the history
PR for release 0.5.0
  • Loading branch information
sotetsuk authored Jan 13, 2019
2 parents e9dcd55 + 92cf05a commit dd7b0f8
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 53 deletions.
22 changes: 14 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,29 @@
# paicli
A CLI tool for PAI (Platform for AI).

## How to install

```
$ pip install paicli
```

## How to build

```sh
$ make build
```

## How to use
## Commands

- initialize config file: `$ paicli config`
- submit a job: `$ paicli submit job_config.json`
- ssh to a container: `$ paicli ssh`. Then select a job name (or specify the job name with `-j` option).
- show job list: `$ paicli jobs`
- stop a job: `$ paicli stop`. Then select a job name (or specify the job name with `-j` option)
- generate new access token `$ paicli token`
- **pai config**: initialize the config file.
- **pai jobs**: show job list.
- **pai token**: generate a new access token.
- **pai submit**: submit a job.
- **pai stop**: stop a job.
- **pai ssh**: ssh into a container.

## Config file
Your config file will be set in `$HOME/.paicli`.
**pai config** will create your config file in `$HOME/.paicli`.
You should set your `host`, `port`, `api_port` and `username`.
Also, when you update your access token, you should enter your passwrod.

Expand Down
30 changes: 15 additions & 15 deletions paicli/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,27 +63,25 @@ def get_jobs_jobname(self, jobname):
else:
res.raise_for_status()

def post_jobs(self, job_config_json):
url = "{}/api/{}/jobs".format(self.config.api_uri, self.config.api_version)
headers = self._headers_with_auth()
def get_jobs_jobname_config(self, jobname):
pass

res = requests.post(url, headers=headers, data=job_config_json)
def get_user_username_jobs_jobname_ssh(self, username, jobname):
url = "{}/api/{}/user/{}/jobs/{}/ssh".format(
self.config.api_uri, self.config.api_version, username, jobname
)
res = requests.get(url)

if res.ok:
return to_str(res.content)
else:
res.raise_for_status()

def get_jobs_jobname_config(self, jobname):
pass
def post_user_username_jobs(self, username, job_config_json):
url = "{}/api/{}/user/{}/jobs".format(self.config.api_uri, self.config.api_version, username)
headers = self._headers_with_auth()

def get_jobs_jobname_ssh(self, jobname):
# NOTE DEPRECATED
#
# This api is removed in the latest api
#
url = "{}/api/{}/jobs/{}/ssh".format(self.config.api_uri, self.config.api_version, jobname)
res = requests.get(url)
res = requests.post(url, headers=headers, data=job_config_json)

if res.ok:
return to_str(res.content)
Expand All @@ -99,8 +97,10 @@ def get_user_username_jobs_jobname_ssh(self, username, jobname):
else:
res.raise_for_status()

def put_jobs_jobname_executiontype(self, jobname, value):
url = "{}/api/{}/jobs/{}/executionType".format(self.config.api_uri, self.config.api_version, jobname)
def put_user_username_jobs_jobname_executiontype(self, username, jobname, value):
url = "{}/api/{}/user/{}/jobs/{}/executionType".format(
self.config.api_uri, self.config.api_version, username, jobname
)
headers = self._headers_with_auth()
data = json.dumps({"value": value})

Expand Down
56 changes: 28 additions & 28 deletions paicli/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def _load(config):
try:
config.load()
except FileNotFoundError as e:
print("Config file does not exist. Run 'paicli config'")
print("Config file does not exist. Run 'pai config'")
exit(1)


Expand All @@ -42,8 +42,8 @@ def main():
pass


@click.command("config", help="Add a your configuration in $HOME/.paicli")
@click.option("--profile", type=str, default="default", help="Add another profile configuration.")
@click.command('config', help="Add a your configuration in $HOME/.paicli")
@click.option('--profile', '-p', type=str, default='default', help="Add another profile configuration.")
def configcmd(profile):
config = Config(profile)
try:
Expand All @@ -56,9 +56,9 @@ def configcmd(profile):
config.add_profile() # Anyway, add new profile or modify the profile


@click.command("token", help="Update access token.")
@click.command('token', help="Update access token.")
@click.option('--expiration', '-e', type=int, default=500000, help="Expiration time.")
@click.option("--profile", type=str, default="default", help="Use a specified profile.")
@click.option('--profile', '-p', type=str, default='default', help="Use a specified profile.")
def tokencmd(expiration, profile):
config = Config(profile)
_load(config)
Expand All @@ -72,14 +72,14 @@ def tokencmd(expiration, profile):
exit(1)


@click.command(name="ssh", help="SSH into a running container in PAI.")
@click.argument('jobname', type=str, default="")
@click.option('--task-name', '-t', type=str, default="")
@click.command(name='ssh', help="SSH into a running container in PAI.")
@click.argument('jobname', type=str, default='')
@click.option('--task-name', '-t', type=str, default='')
@click.option('--task-index', '-i', type=int, default=-1)
@click.option('--username', '-u', type=str, default="")
@click.option('--command', '-c', type=str, default="")
@click.option('--username', '-u', type=str, default='')
@click.option('--command', '-c', type=str, default='')
@click.option('--dryrun', '-d', is_flag=True)
@click.option("--profile", type=str, default="default", help="Use a specified profile.")
@click.option('--profile', '-p', type=str, default='default', help="Use a specified profile.")
def sshcmd(jobname, task_name, task_index, username, command, dryrun, profile):
config = Config(profile)
_load(config)
Expand All @@ -105,7 +105,7 @@ def sshcmd(jobname, task_name, task_index, username, command, dryrun, profile):
# This method is duplicated in the latest API
# So this nested try-catch should be removed in the near future
try:
content = json.loads(api.get_jobs_jobname_ssh(_jobname))
content = json.loads(api.get_user_username_jobs_jobname_ssh(config.username, _jobname))
except requests.HTTPError as e:
status_code = e.response.status_code
if status_code == 404:
Expand All @@ -125,12 +125,12 @@ def sshcmd(jobname, task_name, task_index, username, command, dryrun, profile):
exit(1)


@click.command(name="jobs", help="Show jobs in PAI.")
@click.command(name='jobs', help="Show jobs in PAI.")
@click.option('--username', '-u', multiple=True)
@click.option('--state', '-s', multiple=True)
@click.option('-n', type=int, default=20)
@click.option("--profile", type=str, default="default", help="Use a specified profile.")
def jobscmd(username, state, n, profile):
@click.option('--num-jobs', '-n', type=int, default=20)
@click.option('--profile', '-p', type=str, default='default', help="Use a specified profile.")
def jobscmd(username, state, num_jobs, profile):
config = Config(profile)
_load(config)
api = API(config)
Expand All @@ -143,13 +143,13 @@ def jobscmd(username, state, n, profile):
filter_dic['state'] = state
if filter_dic:
jobs.filter(filter_dic)
jobs.show(n)
jobs.show(num_jobs)


@click.command(name="submit",
@click.command(name='submit',
help="Submit your job into PAI. With no json files, or when '-' is specified, read standard input.")
@click.argument('job_config_json', nargs=-1, required=False)
@click.option("--profile", type=str, default="default", help="Use a specified profile.")
@click.option('--profile', '-p', type=str, default='default', help="Use a specified profile.")
def submitcmd(job_config_json, profile):
config = Config(profile)
_load(config)
Expand All @@ -168,15 +168,15 @@ def submitcmd(job_config_json, profile):

for _job_config_json in job_config_json_list:
try:
api.post_jobs(_job_config_json)
api.post_user_username_jobs(config.username, _job_config_json)
print(colored("Successfully submitted!", "green") + ": {}"
.format(json.loads(_job_config_json)['jobName']))
except requests.HTTPError as e:
status_code = e.response.status_code
if status_code == 401:
print(colored("Submission failed.", "red"))
print("Access token seems to be expired.")
print("Update your token by 'paicli token', then try again.\n")
print("Update your token by 'pai token', then try again.\n")
elif status_code == 400:
print(colored("Submission failed.", "red"))
print("This may be caused by duplicated submission.\n")
Expand All @@ -198,13 +198,13 @@ def submitcmd(job_config_json, profile):
exit(1)
except FileNotFoundError as e:
print(colored("Submission failed.\n", "red"))
print("Access token does not exist. Run 'paicli token'")
print("Access token does not exist. Run 'pai token'")
exit(1)


@click.command(name="stop", help="Stop a job in PAI.")
@click.command(name='stop', help="Stop a job in PAI.")
@click.argument('jobname', type=str, nargs=-1)
@click.option("--profile", type=str, default="default", help="Use a specified profile.")
@click.option('--profile', '-p', type=str, default='default', help="Use a specified profile.")
def stopcmd(jobname, profile):
config = Config(profile)
_load(config)
Expand All @@ -218,7 +218,7 @@ def stopcmd(jobname, profile):

for _jobname in jobname:
try:
api.put_jobs_jobname_executiontype(_jobname, "STOP")
api.put_user_username_jobs_jobname_executiontype(config.username, _jobname, "STOP")
print(colored("Stop signal submitted!", "green") + ": {}".format(_jobname))
except requests.HTTPError as e:
print(colored("Failed to submit a stop signal.\n", "red"))
Expand All @@ -238,13 +238,13 @@ def stopcmd(jobname, profile):
exit(1)
except FileNotFoundError:
print(colored("Failed to submit a stop signal.\n", "red"))
print("Access token does not exist. Run 'paicli token'")
print("Access token does not exist. Run 'pai token'")
exit(1)


@click.command(name="host", help="Show host information of a job.")
@click.command(name='host', help="Show host information of a job.")
@click.argument('jobname', type=str)
@click.option("--profile", type=str, default="default", help="Use a specified profile.")
@click.option('--profile', '-p', type=str, default='default', help="Use a specified profile.")
def hostcmd(jobname, profile):
config = Config(profile)
_load(config)
Expand Down
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

setup(
name='paicli',
version="0.4.2",
version="0.5.0",
description='Client for PAI',
author='Sotetsu KOYAMADA',
url='',
Expand All @@ -18,7 +18,7 @@
],
packages=find_packages(),
entry_points={
'console_scripts': 'paicli = paicli.main:main'
'console_scripts': 'pai = paicli.main:main'
},
classifiers=[
"Programming Language :: Python :: 3.5",
Expand Down

0 comments on commit dd7b0f8

Please sign in to comment.