From 53f188222aa23b58694a83a48707ea7dda4dce14 Mon Sep 17 00:00:00 2001 From: Shotaro Kohama Date: Wed, 6 May 2020 22:20:58 -0700 Subject: [PATCH 1/7] Add the 'kfp experiment list' command --- sdk/python/kfp/cli/cli.py | 2 ++ sdk/python/kfp/cli/experiment.py | 40 ++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 sdk/python/kfp/cli/experiment.py diff --git a/sdk/python/kfp/cli/cli.py b/sdk/python/kfp/cli/cli.py index 3c3f497dfba..d56e4c84e6d 100644 --- a/sdk/python/kfp/cli/cli.py +++ b/sdk/python/kfp/cli/cli.py @@ -19,6 +19,7 @@ from .run import run from .pipeline import pipeline from .diagnose_me_cli import diagnose_me +from .experiment import experiment @click.group() @click.option('--endpoint', help='Endpoint of the KFP API service to connect.') @@ -40,6 +41,7 @@ def main(): cli.add_command(run) cli.add_command(pipeline) cli.add_command(diagnose_me,'diagnose_me') + cli.add_command(experiment) try: cli(obj={}, auto_envvar_prefix='KFP') except Exception as e: diff --git a/sdk/python/kfp/cli/experiment.py b/sdk/python/kfp/cli/experiment.py new file mode 100644 index 00000000000..c12f03b7d5f --- /dev/null +++ b/sdk/python/kfp/cli/experiment.py @@ -0,0 +1,40 @@ + +import click +import logging +from tabulate import tabulate + + +@click.group() +def experiment(): + """Manage experiment resources""" + pass + +@experiment.command() +@click.option( + '--max-size', + default=100, + help="Max size of the listed experiments." +) +@click.pass_context +def list(ctx, max_size): + """List experiments""" + client = ctx.obj['client'] + + response = client.list_experiments( + page_size=max_size, + sort_by="created_at desc" + ) + if response.experiments: + _display_experiments(response.experiments) + else: + logging.info("No experiments found") + + +def _display_experiments(experiments): + headers = ["Experiment ID", "Name", "Created at"] + data = [[ + exp.id, + exp.name, + exp.created_at.isoformat() + ] for exp in experiments] + print(tabulate(data, headers=headers, tablefmt="grid")) From 53692f48f21996f9c1aef2fb76410ca6bd24d7f7 Mon Sep 17 00:00:00 2001 From: Shotaro Kohama Date: Wed, 6 May 2020 22:31:08 -0700 Subject: [PATCH 2/7] Add the 'kfp experiment get' command --- sdk/python/kfp/cli/experiment.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/sdk/python/kfp/cli/experiment.py b/sdk/python/kfp/cli/experiment.py index c12f03b7d5f..fef073cb756 100644 --- a/sdk/python/kfp/cli/experiment.py +++ b/sdk/python/kfp/cli/experiment.py @@ -30,6 +30,17 @@ def list(ctx, max_size): logging.info("No experiments found") +@experiment.command() +@click.argument("experiment-id") +@click.pass_context +def get(ctx, experiment_id): + """Get detailed information about an experiment""" + client = ctx.obj["client"] + + response = client.get_experiment(experiment_id) + _display_experiment(response) + + def _display_experiments(experiments): headers = ["Experiment ID", "Name", "Created at"] data = [[ @@ -38,3 +49,14 @@ def _display_experiments(experiments): exp.created_at.isoformat() ] for exp in experiments] print(tabulate(data, headers=headers, tablefmt="grid")) + + +def _display_experiment(exp): + print(tabulate([], headers=["Experiment Details"])) + table = [ + ["ID", exp.id], + ["Name", exp.name], + ["Description", exp.description], + ["Created at", exp.created_at.isoformat()], + ] + print(tabulate(table, tablefmt="plain")) \ No newline at end of file From a9ae5a6338739b9289d93282e17f3054d31437be Mon Sep 17 00:00:00 2001 From: Shotaro Kohama Date: Wed, 6 May 2020 22:46:16 -0700 Subject: [PATCH 3/7] Add the 'kfp experiment create' command --- sdk/python/kfp/cli/experiment.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/sdk/python/kfp/cli/experiment.py b/sdk/python/kfp/cli/experiment.py index fef073cb756..294611140f6 100644 --- a/sdk/python/kfp/cli/experiment.py +++ b/sdk/python/kfp/cli/experiment.py @@ -1,4 +1,3 @@ - import click import logging from tabulate import tabulate @@ -9,6 +8,23 @@ def experiment(): """Manage experiment resources""" pass + +@experiment.command() +@click.option( + '--description', + help="Description of the experiment." +) +@click.argument("name") +@click.pass_context +def create(ctx, description, name): + """Create an experiment""" + client = ctx.obj["client"] + + response = client.create_experiment(name, description=description) + logging.info("Experiment {} has been submitted\n".format(name)) + _display_experiment(response) + + @experiment.command() @click.option( '--max-size', From ab538d118f3744f3679b0e625298d0840efbd503 Mon Sep 17 00:00:00 2001 From: Shotaro Kohama Date: Wed, 6 May 2020 23:05:33 -0700 Subject: [PATCH 4/7] Add the 'kfp experiment delete' command --- sdk/python/kfp/cli/experiment.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/sdk/python/kfp/cli/experiment.py b/sdk/python/kfp/cli/experiment.py index 294611140f6..7709654be74 100644 --- a/sdk/python/kfp/cli/experiment.py +++ b/sdk/python/kfp/cli/experiment.py @@ -57,6 +57,17 @@ def get(ctx, experiment_id): _display_experiment(response) +@experiment.command() +@click.argument("experiment-id") +@click.pass_context +def delete(ctx, experiment_id): + """Delete an experiment""" + client = ctx.obj["client"] + + client.experiments.delete_experiment(id=experiment_id) + print("{} is deleted.".format(experiment_id)) + + def _display_experiments(experiments): headers = ["Experiment ID", "Name", "Created at"] data = [[ From 9de466d0555500849f68eac8a08c8a5f9623f2d6 Mon Sep 17 00:00:00 2001 From: Shotaro Kohama Date: Mon, 11 May 2020 09:41:59 -0700 Subject: [PATCH 5/7] Add a caution to 'kfp experiment delete' --- sdk/python/kfp/cli/experiment.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sdk/python/kfp/cli/experiment.py b/sdk/python/kfp/cli/experiment.py index 7709654be74..eec2192d7cc 100644 --- a/sdk/python/kfp/cli/experiment.py +++ b/sdk/python/kfp/cli/experiment.py @@ -62,6 +62,13 @@ def get(ctx, experiment_id): @click.pass_context def delete(ctx, experiment_id): """Delete an experiment""" + + confirmation = "Caution. The RunDetails page could have an issue" \ + " when to render a run that has no experiment." \ + " Do you want to continue?" + if not click.confirm(confirmation): + return + client = ctx.obj["client"] client.experiments.delete_experiment(id=experiment_id) From 5b16b1aa12d9c7042deb5b0dcf26a39168cdda74 Mon Sep 17 00:00:00 2001 From: Shotaro Kohama Date: Mon, 11 May 2020 09:47:51 -0700 Subject: [PATCH 6/7] Use directly the backend api method to list experiments --- sdk/python/kfp/cli/experiment.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/python/kfp/cli/experiment.py b/sdk/python/kfp/cli/experiment.py index eec2192d7cc..a6eff56d2ce 100644 --- a/sdk/python/kfp/cli/experiment.py +++ b/sdk/python/kfp/cli/experiment.py @@ -36,7 +36,7 @@ def list(ctx, max_size): """List experiments""" client = ctx.obj['client'] - response = client.list_experiments( + response = client.experiments.list_experiment( page_size=max_size, sort_by="created_at desc" ) From e6b43f173d15f23cc52b1f91b3505b0231aa39e0 Mon Sep 17 00:00:00 2001 From: Shotaro Kohama Date: Mon, 18 May 2020 22:13:23 -0700 Subject: [PATCH 7/7] Update a message based on the suggestion https://github.com/kubeflow/pipelines/pull/3705#discussion_r424751792 --- sdk/python/kfp/cli/experiment.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sdk/python/kfp/cli/experiment.py b/sdk/python/kfp/cli/experiment.py index a6eff56d2ce..92719996e2f 100644 --- a/sdk/python/kfp/cli/experiment.py +++ b/sdk/python/kfp/cli/experiment.py @@ -64,7 +64,7 @@ def delete(ctx, experiment_id): """Delete an experiment""" confirmation = "Caution. The RunDetails page could have an issue" \ - " when to render a run that has no experiment." \ + " when it renders a run that has no experiment." \ " Do you want to continue?" if not click.confirm(confirmation): return @@ -93,4 +93,4 @@ def _display_experiment(exp): ["Description", exp.description], ["Created at", exp.created_at.isoformat()], ] - print(tabulate(table, tablefmt="plain")) \ No newline at end of file + print(tabulate(table, tablefmt="plain"))