pipelines/sdk/python/kfp/cli/recurring_run.py

277 lines
9.2 KiB
Python

# Copyright 2021-2022 The Kubeflow Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from typing import Any, Dict, List, Optional
import click
from kfp import client
from kfp.cli import output
from kfp.cli.utils import parsing
@click.group()
def recurring_run():
"""Manage recurring run resources."""
either_option_required = 'Either --experiment-id or --experiment-name is required.'
@recurring_run.command()
@click.option(
'--catchup/--no-catchup',
type=bool,
help=parsing.get_param_descr(client.Client.create_recurring_run,
'no_catchup'),
)
@click.option(
'--cron-expression',
help=parsing.get_param_descr(client.Client.create_recurring_run,
'cron_expression'))
@click.option(
'--description',
help=parsing.get_param_descr(client.Client.create_recurring_run,
'description'))
@click.option(
'--enable-caching/--disable-caching',
type=bool,
default=None,
help=parsing.get_param_descr(client.Client.create_recurring_run,
'enable_caching'),
)
@click.option(
'--enabled/--disabled',
type=bool,
help=parsing.get_param_descr(client.Client.create_recurring_run, 'enabled'))
@click.option(
'--end-time',
help=parsing.get_param_descr(client.Client.create_recurring_run,
'end_time'))
@click.option(
'--experiment-id',
help=parsing.get_param_descr(client.Client.create_recurring_run,
'experiment_id') + ' ' + either_option_required
)
@click.option(
'--experiment-name',
help='The name of the experiment to create the recurring run under.' + ' ' +
either_option_required)
@click.option(
'--job-name',
help=parsing.get_param_descr(client.Client.create_recurring_run,
'job_name'))
@click.option(
'--interval-second',
help=parsing.get_param_descr(client.Client.create_recurring_run,
'interval_second'))
@click.option(
'--max-concurrency',
type=int,
default=1,
help=parsing.get_param_descr(client.Client.create_recurring_run,
'max_concurrency'),
)
@click.option(
'--pipeline-id',
help=parsing.get_param_descr(client.Client.create_recurring_run,
'pipeline_id'),
)
@click.option(
'--pipeline-package-path',
type=click.Path(exists=True, dir_okay=False),
help=parsing.get_param_descr(client.Client.create_recurring_run,
'pipeline_package_path'))
@click.option(
'--start-time',
help=parsing.get_param_descr(client.Client.create_recurring_run,
'start_time'))
@click.option('--version-id', help='The id of a pipeline version.')
@click.argument('args', nargs=-1)
@click.pass_context
def create(ctx: click.Context,
job_name: str,
experiment_id: Optional[str] = None,
experiment_name: Optional[str] = None,
catchup: Optional[bool] = None,
cron_expression: Optional[str] = None,
enabled: Optional[bool] = None,
description: Optional[str] = None,
enable_caching: Optional[bool] = None,
end_time: Optional[str] = None,
interval_second: Optional[int] = None,
max_concurrency: Optional[int] = None,
pipeline_package_path: Optional[str] = None,
pipeline_id: Optional[str] = None,
start_time: Optional[str] = None,
version_id: Optional[str] = None,
args: Optional[List[str]] = None):
"""Create a recurring run."""
client_obj: client.Client = ctx.obj['client']
output_format = ctx.obj['output']
if enable_caching is not None:
click.echo(
'--enable-caching and --disable-caching options are not yet supported.'
)
enable_caching = None
if (interval_second is None) == (cron_expression is None):
raise ValueError(
'Either of --interval-second or --cron-expression options is required.'
)
if (experiment_id is None) == (experiment_name is None):
raise ValueError(either_option_required)
if not experiment_id:
experiment = client_obj.create_experiment(experiment_name)
experiment_id = experiment.experiment_id
# Ensure we only split on the first equals char so the value can contain
# equals signs too.
split_args: List = [arg.split('=', 1) for arg in args or []]
params: Dict[str, Any] = dict(split_args)
recurring_run = client_obj.create_recurring_run(
cron_expression=cron_expression,
description=description,
enabled=enabled,
enable_caching=enable_caching,
end_time=end_time,
experiment_id=experiment_id,
interval_second=interval_second,
job_name=job_name,
max_concurrency=max_concurrency,
no_catchup=not catchup,
params=params,
pipeline_package_path=pipeline_package_path,
pipeline_id=pipeline_id,
start_time=start_time,
version_id=version_id)
output.print_output(
recurring_run,
output.ModelType.RECURRING_RUN,
output_format,
)
@recurring_run.command()
@click.option(
'-e',
'--experiment-id',
help=parsing.get_param_descr(client.Client.list_recurring_runs,
'experiment_id'))
@click.option(
'--page-token',
default='',
help=parsing.get_param_descr(client.Client.list_recurring_runs,
'page_token'))
@click.option(
'-m',
'--max-size',
default=100,
help=parsing.get_param_descr(client.Client.list_recurring_runs,
'page_size'))
@click.option(
'--sort-by',
default='created_at desc',
help=parsing.get_param_descr(client.Client.list_recurring_runs, 'sort_by'))
@click.option(
'--filter',
help=parsing.get_param_descr(client.Client.list_recurring_runs, 'filter'))
@click.pass_context
def list(ctx: click.Context, experiment_id: str, page_token: str, max_size: int,
sort_by: str, filter: str):
"""List recurring runs."""
client_obj: client.Client = ctx.obj['client']
output_format = ctx.obj['output']
response = client_obj.list_recurring_runs(
experiment_id=experiment_id,
page_token=page_token,
page_size=max_size,
sort_by=sort_by,
filter=filter)
output.print_output(
response.recurring_runs or [],
output.ModelType.RECURRING_RUN,
output_format,
)
@recurring_run.command()
@click.argument('recurring-run-id')
@click.pass_context
def get(ctx: click.Context, recurring_run_id: str):
"""Get information about a recurring run."""
client_obj: client.Client = ctx.obj['client']
output_format = ctx.obj['output']
recurring_run = client_obj.get_recurring_run(recurring_run_id)
output.print_output(
recurring_run,
output.ModelType.RECURRING_RUN,
output_format,
)
@recurring_run.command()
@click.argument('recurring-run-id')
@click.pass_context
def delete(ctx: click.Context, recurring_run_id: str):
"""Delete a recurring run."""
client_obj: client.Client = ctx.obj['client']
output_format = ctx.obj['output']
confirmation = f'Are you sure you want to delete job {recurring_run_id}?'
if not click.confirm(confirmation):
return
client_obj.delete_recurring_run(recurring_run_id)
output.print_deleted_text('recurring_run', recurring_run_id, output_format)
@recurring_run.command()
@click.argument('recurring-run-id')
@click.pass_context
def enable(ctx: click.Context, recurring_run_id: str):
"""Enable a recurring run."""
client_obj: client.Client = ctx.obj['client']
output_format = ctx.obj['output']
client_obj.enable_recurring_run(recurring_run_id=recurring_run_id)
# TODO: add wait option, since enable takes time to complete
recurring_run = client_obj.get_recurring_run(
recurring_run_id=recurring_run_id)
output.print_output(
recurring_run,
output.ModelType.RECURRING_RUN,
output_format,
)
@recurring_run.command()
@click.argument('recurring-run-id')
@click.pass_context
def disable(ctx: click.Context, recurring_run_id: str):
"""Disable a recurring run."""
client_obj: client.Client = ctx.obj['client']
output_format = ctx.obj['output']
client_obj.disable_recurring_run(recurring_run_id=recurring_run_id)
# TODO: add wait option, since disable takes time to complete
recurring_run = client_obj.get_recurring_run(
recurring_run_id=recurring_run_id)
output.print_output(
recurring_run,
output.ModelType.RECURRING_RUN,
output_format,
)