Best Python code snippet using ATX
main.py
Source:main.py
1import importlib as _importlib2import os3import os as _os4import stat as _stat5import sys as _sys6from typing import Callable, Dict, List, Tuple, Union7import click as _click8import requests as _requests9import six as _six10from flyteidl.admin import launch_plan_pb2 as _launch_plan_pb211from flyteidl.admin import task_pb2 as _task_pb212from flyteidl.admin import workflow_pb2 as _workflow_pb213from flyteidl.core import identifier_pb2 as _identifier_pb214from flyteidl.core import literals_pb2 as _literals_pb215from flyteidl.core import tasks_pb2 as _core_tasks_pb216from flyteidl.core import workflow_pb2 as _core_workflow_pb217from google.protobuf.json_format import MessageToJson18from google.protobuf.pyext.cpp_message import GeneratedProtocolMessageType as _GeneratedProtocolMessageType19from flytekit import __version__20from flytekit.clients import friendly as _friendly_client21from flytekit.clis.helpers import construct_literal_map_from_parameter_map as _construct_literal_map_from_parameter_map22from flytekit.clis.helpers import construct_literal_map_from_variable_map as _construct_literal_map_from_variable_map23from flytekit.clis.helpers import hydrate_registration_parameters24from flytekit.clis.helpers import parse_args_into_dict as _parse_args_into_dict25from flytekit.common import launch_plan as _launch_plan_common26from flytekit.common import utils as _utils27from flytekit.common import workflow_execution as _workflow_execution_common28from flytekit.common.core import identifier as _identifier29from flytekit.common.exceptions import user as _user_exceptions30from flytekit.common.tasks import task as _tasks_common31from flytekit.common.types import helpers as _type_helpers32from flytekit.common.utils import load_proto_from_file as _load_proto_from_file33from flytekit.configuration import auth as _auth_config34from flytekit.configuration import platform as _platform_config35from flytekit.configuration import set_flyte_config_file36from flytekit.interfaces.data import data_proxy as _data_proxy37from flytekit.interfaces.data.data_proxy import Data38from flytekit.models import common as _common_models39from flytekit.models import filters as _filters40from flytekit.models import launch_plan as _launch_plan41from flytekit.models import literals as _literals42from flytekit.models import named_entity as _named_entity43from flytekit.models.admin import common as _admin_common44from flytekit.models.common import AuthRole as _AuthRole45from flytekit.models.common import RawOutputDataConfig as _RawOutputDataConfig46from flytekit.models.core import execution as _core_execution_models47from flytekit.models.core import identifier as _core_identifier48from flytekit.models.execution import ExecutionMetadata as _ExecutionMetadata49from flytekit.models.execution import ExecutionSpec as _ExecutionSpec50from flytekit.models.matchable_resource import ClusterResourceAttributes as _ClusterResourceAttributes51from flytekit.models.matchable_resource import ExecutionClusterLabel as _ExecutionClusterLabel52from flytekit.models.matchable_resource import ExecutionQueueAttributes as _ExecutionQueueAttributes53from flytekit.models.matchable_resource import MatchableResource as _MatchableResource54from flytekit.models.matchable_resource import MatchingAttributes as _MatchingAttributes55from flytekit.models.matchable_resource import PluginOverride as _PluginOverride56from flytekit.models.matchable_resource import PluginOverrides as _PluginOverrides57from flytekit.models.project import Project as _Project58from flytekit.models.schedule import Schedule as _Schedule59from flytekit.tools.fast_registration import get_additional_distribution_loc as _get_additional_distribution_loc60try: # Python 361 import urllib.parse as _urlparse62except ImportError: # Python 263 import urlparse as _urlparse64_tt = _six.text_type65# Similar to how kubectl has a config file in the users home directory, this Flyte CLI will also look for one.66# The format of this config file is the same as a workflow's config file, except that the relevant fields are different.67# Please see the example.config file68_default_config_file_dir = ".flyte"69_default_config_file_name = "config"70def _welcome_message():71 _click.secho("Welcome to Flyte CLI! Version: {}".format(_tt(__version__)), bold=True)72def _get_user_filepath_home():73 return _os.path.expanduser("~")74def _get_config_file_path():75 home = _get_user_filepath_home()76 return _os.path.join(home, _default_config_file_dir, _default_config_file_name)77def _detect_default_config_file():78 config_file = _get_config_file_path()79 if _get_user_filepath_home() and _os.path.exists(config_file):80 _click.secho("Using default config file at {}".format(_tt(config_file)), fg="blue")81 set_flyte_config_file(config_file_path=config_file)82 else:83 _click.secho(84 """Config file not found at default location, relying on environment variables instead.85 To setup your config file run 'flyte-cli setup-config'""",86 fg="blue",87 )88# Run this as the module is loading to pick up settings that click can then use when constructing the commands89_detect_default_config_file()90def _get_io_string(literal_map, verbose=False):91 """92 :param flytekit.models.literals.LiteralMap literal_map:93 :param bool verbose:94 :rtype: Text95 """96 value_dict = _type_helpers.unpack_literal_map_to_sdk_object(literal_map)97 if value_dict:98 return "\n" + "\n".join(99 "{:30}: {}".format(100 k,101 _prefix_lines(102 "{:30} ".format(""),103 v.verbose_string() if verbose else v.short_string(),104 ),105 )106 for k, v in _six.iteritems(value_dict)107 )108 else:109 return "(None)"110def _fetch_and_stringify_literal_map(path, verbose=False):111 """112 :param Text path:113 :param bool verbose:114 :rtype: Text115 """116 with _utils.AutoDeletingTempDir("flytecli") as tmp:117 try:118 fname = tmp.get_named_tempfile("literalmap.pb")119 _data_proxy.Data.get_data(path, fname)120 literal_map = _literals.LiteralMap.from_flyte_idl(121 _utils.load_proto_from_file(_literals_pb2.LiteralMap, fname)122 )123 return _get_io_string(literal_map, verbose=verbose)124 except Exception:125 return "Failed to pull data from {}. Do you have permissions?".format(path)126def _prefix_lines(prefix, txt):127 """128 :param Text prefix:129 :param Text txt:130 :rtype: Text131 """132 return "\n{}".format(prefix).join(txt.splitlines())133def _secho_workflow_status(status, nl=True):134 red_phases = {135 _core_execution_models.WorkflowExecutionPhase.FAILED,136 _core_execution_models.WorkflowExecutionPhase.ABORTED,137 _core_execution_models.WorkflowExecutionPhase.FAILING,138 _core_execution_models.WorkflowExecutionPhase.TIMED_OUT,139 }140 yellow_phases = {141 _core_execution_models.WorkflowExecutionPhase.QUEUED,142 _core_execution_models.WorkflowExecutionPhase.UNDEFINED,143 }144 green_phases = {145 _core_execution_models.WorkflowExecutionPhase.SUCCEEDED,146 _core_execution_models.WorkflowExecutionPhase.SUCCEEDING,147 }148 if status in red_phases:149 fg = "red"150 elif status in yellow_phases:151 fg = "yellow"152 elif status in green_phases:153 fg = "green"154 else:155 fg = "blue"156 _click.secho(157 "{:10} ".format(_tt(_core_execution_models.WorkflowExecutionPhase.enum_to_string(status))),158 bold=True,159 fg=fg,160 nl=nl,161 )162def _secho_node_execution_status(status, nl=True):163 red_phases = {164 _core_execution_models.NodeExecutionPhase.FAILING,165 _core_execution_models.NodeExecutionPhase.FAILED,166 _core_execution_models.NodeExecutionPhase.ABORTED,167 _core_execution_models.NodeExecutionPhase.TIMED_OUT,168 }169 yellow_phases = {170 _core_execution_models.NodeExecutionPhase.QUEUED,171 _core_execution_models.NodeExecutionPhase.UNDEFINED,172 }173 green_phases = {_core_execution_models.NodeExecutionPhase.SUCCEEDED}174 if status in red_phases:175 fg = "red"176 elif status in yellow_phases:177 fg = "yellow"178 elif status in green_phases:179 fg = "green"180 else:181 fg = "blue"182 _click.secho(183 "{:10} ".format(_tt(_core_execution_models.NodeExecutionPhase.enum_to_string(status))),184 bold=True,185 fg=fg,186 nl=nl,187 )188def _secho_task_execution_status(status, nl=True):189 red_phases = {190 _core_execution_models.TaskExecutionPhase.ABORTED,191 _core_execution_models.TaskExecutionPhase.FAILED,192 }193 yellow_phases = {194 _core_execution_models.TaskExecutionPhase.QUEUED,195 _core_execution_models.TaskExecutionPhase.UNDEFINED,196 _core_execution_models.TaskExecutionPhase.RUNNING,197 }198 green_phases = {_core_execution_models.TaskExecutionPhase.SUCCEEDED}199 if status in red_phases:200 fg = "red"201 elif status in yellow_phases:202 fg = "yellow"203 elif status in green_phases:204 fg = "green"205 else:206 fg = "blue"207 _click.secho(208 "{:10} ".format(_tt(_core_execution_models.TaskExecutionPhase.enum_to_string(status))),209 bold=True,210 fg=fg,211 nl=nl,212 )213def _secho_one_execution(ex, urns_only):214 if not urns_only:215 _click.echo(216 "{:100} {:40} {:40}".format(217 _tt(_identifier.WorkflowExecutionIdentifier.promote_from_model(ex.id)),218 _tt(ex.id.name),219 _tt(ex.spec.launch_plan.name),220 ),221 nl=False,222 )223 _secho_workflow_status(ex.closure.phase)224 else:225 _click.echo(226 "{:100}".format(_tt(_identifier.WorkflowExecutionIdentifier.promote_from_model(ex.id))),227 nl=True,228 )229def _terminate_one_execution(client, urn, cause, shouldPrint=True):230 if shouldPrint:231 _click.echo("{:100} {:40}".format(_tt(urn), _tt(cause)))232 client.terminate_execution(_identifier.WorkflowExecutionIdentifier.from_python_std(urn), cause)233def _update_one_launch_plan(urn, host, insecure, state):234 client = _friendly_client.SynchronousFlyteClient(host, insecure=insecure)235 if state == "active":236 state = _launch_plan.LaunchPlanState.ACTIVE237 else:238 state = _launch_plan.LaunchPlanState.INACTIVE239 client.update_launch_plan(_identifier.Identifier.from_python_std(urn), state)240 _click.echo("Successfully updated {}".format(_tt(urn)))241def _render_schedule_expr(lp):242 sched_expr = "NONE"243 if lp.spec.entity_metadata.schedule and lp.spec.entity_metadata.schedule.cron_expression:244 sched_expr = "cron({cron_expr})".format(cron_expr=_tt(lp.spec.entity_metadata.schedule.cron_expression))245 elif lp.spec.entity_metadata.schedule and lp.spec.entity_metadata.schedule.rate:246 sched_expr = "rate({unit}={value})".format(247 unit=_tt(_Schedule.FixedRateUnit.enum_to_string(lp.spec.entity_metadata.schedule.rate.unit)),248 value=_tt(lp.spec.entity_metadata.schedule.rate.value),249 )250 return "{:30}".format(sched_expr)251# These two flags are special in that they are specifiable in both the user's default ~/.flyte/config file, and in the252# flyte-cli command itself, both in the parent-command position (flyte-cli) , and in the child-command position253# (e.g. list-task-names). To get around this, first we read the value of the config object, and store it. Later in the254# file below are options for each of these options, one for the parent command, and one for the child command. If not255# set by the parent, and also not set by the child, then the value from the config file is used.256#257# For both host and insecure, command line values will override the setting in ~/.flyte/config file.258#259# The host url option is a required setting, so if missing it will fail, but it may be set in the click command, so we260# don't have to check now. It will be checked later.261_HOST_URL = None262try:263 _HOST_URL = _platform_config.URL.get()264except _user_exceptions.FlyteAssertion:265 pass266_INSECURE_FLAG = _platform_config.INSECURE.get()267_PROJECT_FLAGS = ["-p", "--project"]268_DOMAIN_FLAGS = ["-d", "--domain"]269_NAME_FLAGS = ["-n", "--name"]270_VERSION_FLAGS = ["-v", "--version"]271_HOST_FLAGS = ["-h", "--host"]272_PRINCIPAL_FLAGS = ["-r", "--principal"]273_INSECURE_FLAGS = ["-i", "--insecure"]274_project_option = _click.option(*_PROJECT_FLAGS, required=True, help="The project namespace to query.")275_optional_project_option = _click.option(276 *_PROJECT_FLAGS,277 required=False,278 default=None,279 help="[Optional] The project namespace to query.",280)281_domain_option = _click.option(*_DOMAIN_FLAGS, required=True, help="The domain namespace to query.")282_optional_domain_option = _click.option(283 *_DOMAIN_FLAGS,284 required=False,285 default=None,286 help="[Optional] The domain namespace to query.",287)288_name_option = _click.option(*_NAME_FLAGS, required=True, help="The name to query.")289_optional_name_option = _click.option(290 *_NAME_FLAGS,291 required=False,292 type=str,293 default=None,294 help="[Optional] The name to query.",295)296_principal_option = _click.option(*_PRINCIPAL_FLAGS, required=True, help="Your team name, or your name")297_optional_principal_option = _click.option(298 *_PRINCIPAL_FLAGS,299 required=False,300 type=str,301 default=None,302 help="[Optional] Your team name, or your name",303)304_insecure_option = _click.option(*_INSECURE_FLAGS, is_flag=True, required=True, help="Do not use SSL")305_urn_option = _click.option("-u", "--urn", required=True, help="The unique identifier for an entity.")306_optional_urn_option = _click.option("-u", "--urn", required=False, help="The unique identifier for an entity.")307_host_option = _click.option(308 *_HOST_FLAGS,309 required=not bool(_HOST_URL),310 default=_HOST_URL,311 help="The URL for the Flyte Admin Service. If you intend for this to be consistent, set the FLYTE_PLATFORM_URL "312 "environment variable to the desired URL and this will not need to be set.",313)314_token_option = _click.option(315 "-t",316 "--token",317 required=False,318 default="",319 type=str,320 help="Pagination token from which to start listing in the list of results.",321)322_limit_option = _click.option(323 "-l",324 "--limit",325 required=False,326 default=100,327 type=int,328 help="Maximum number of results to return for this call.",329)330_show_all_option = _click.option(331 "-a",332 "--show-all",333 is_flag=True,334 default=False,335 help="Set this flag to page through and list all results.",336)337# TODO: Provide documentation on filter format338_filter_option = _click.option(339 "-f",340 "--filter",341 multiple=True,342 help="""Filter to be applied. Multiple filters can be applied and they will be ANDed together.343 Filters may be supplied as strings such as 'eq(name, workflow_name)'. Additional documentation on filter344 syntax can be found here: https://docs.flyte.org/en/latest/dive_deep/admin_service.html#adding-request-filters""",345)346_state_choice = _click.option(347 "--state",348 type=_click.Choice(["active", "inactive"]),349 required=True,350 help="Whether or not to set schedule as active.",351)352_named_entity_state_choice = _click.option(353 "--state",354 type=_click.Choice(["active", "archived"]),355 required=True,356 help="The state change to apply to a named entity",357)358_named_entity_description_option = _click.option(359 "--description",360 required=False,361 type=str,362 help="Concise description for the entity.",363)364_sort_by_option = _click.option(365 "--sort-by",366 required=False,367 help="Provide an entity field to be sorted. i.e. asc(name) or desc(name)",368)369_show_io_option = _click.option(370 "--show-io",371 is_flag=True,372 default=False,373 help="Set this flag to view inputs and outputs. Pair with the --verbose flag to get the full textual description"374 " inputs and outputs.",375)376_verbose_option = _click.option(377 "--verbose",378 is_flag=True,379 default=False,380 help="Set this flag to view the full textual description of all fields.",381)382_filename_option = _click.option("-f", "--filename", required=True, help="File path of pb file")383_idl_class_option = _click.option(384 "-p",385 "--proto_class",386 required=True,387 help="Dot (.) separated path to Python IDL class. (e.g. flyteidl.core.workflow_closure_pb2.WorkflowClosure)",388)389_cause_option = _click.option(390 "-c",391 "--cause",392 required=True,393 help="The message signaling the cause of the termination of the execution(s)",394)395_optional_urns_only_option = _click.option(396 "--urns-only",397 is_flag=True,398 default=False,399 required=False,400 help="[Optional] Set the flag if you want to output the urn(s) only. Setting this will override the verbose flag",401)402_project_identifier_option = _click.option(403 "-p",404 "--identifier",405 required=True,406 type=str,407 help="Unique identifier for the project.",408)409_project_name_option = _click.option(410 "-n",411 "--name",412 required=True,413 type=str,414 help="The human-readable name for the project.",415)416_project_description_option = _click.option(417 "-d",418 "--description",419 required=True,420 type=str,421 help="Concise description for the project.",422)423_watch_option = _click.option(424 "-w",425 "--watch",426 is_flag=True,427 default=False,428 help="Set the flag if you want the command to keep watching the execution until its completion",429)430_assumable_iam_role_option = _click.option(431 "--assumable-iam-role", help="Custom assumable iam auth role to register launch plans with"432)433_kubernetes_service_acct_option = _click.option(434 "-s",435 "--kubernetes-service-account",436 help="Custom kubernetes service account auth role to register launch plans with",437)438_output_location_prefix_option = _click.option(439 "-o", "--output-location-prefix", help="Custom output location prefix for offloaded types (files/schemas)"440)441_files_argument = _click.argument(442 "files",443 type=_click.Path(exists=True),444 nargs=-1,445)446class _FlyteSubCommand(_click.Command):447 _PASSABLE_ARGS = {448 "project": _PROJECT_FLAGS[0],449 "domain": _DOMAIN_FLAGS[0],450 "name": _NAME_FLAGS[0],451 "host": _HOST_FLAGS[0],452 }453 _PASSABLE_FLAGS = {454 "insecure": _INSECURE_FLAGS[0],455 }456 def make_context(self, cmd_name, args, parent=None):457 prefix_args = []458 for param in self.params:459 if (460 param.name in type(self)._PASSABLE_ARGS461 and param.name in parent.params462 and parent.params[param.name] is not None463 ):464 prefix_args.extend([type(self)._PASSABLE_ARGS[param.name], _six.text_type(parent.params[param.name])])465 # For flags, we don't append the value of the flag, otherwise click will fail to parse466 if param.name in type(self)._PASSABLE_FLAGS and param.name in parent.params and parent.params[param.name]:467 prefix_args.append(type(self)._PASSABLE_FLAGS[param.name])468 # This is where we handle the value read from the flyte-cli config file, if any, for the insecure flag.469 # Previously we tried putting it into the default into the declaration of the option itself, but in click, it470 # appears that flags operate like toggles. If both the default is true and the flag is passed in the command,471 # they negate each other and it's as if it's not passed. Here we rectify that.472 if _INSECURE_FLAG and _INSECURE_FLAGS[0] not in prefix_args:473 prefix_args.append(_INSECURE_FLAGS[0])474 ctx = super(_FlyteSubCommand, self).make_context(cmd_name, prefix_args + args, parent=parent)475 return ctx476@_click.option(477 *_HOST_FLAGS,478 required=False,479 type=str,480 default=None,481 help="[Optional] The host to pass to the sub-command (if applicable). If set again in the sub-command, "482 "the sub-command's parameter takes precedence.",483)484@_click.option(485 *_PROJECT_FLAGS,486 required=False,487 type=str,488 default=None,489 help="[Optional] The project to pass to the sub-command (if applicable) If set again in the sub-command, "490 "the sub-command's parameter takes precedence.",491)492@_click.option(493 *_DOMAIN_FLAGS,494 required=False,495 type=str,496 default=None,497 help="[Optional] The domain to pass to the sub-command (if applicable) If set again in the sub-command, "498 "the sub-command's parameter takes precedence.",499)500@_click.option(501 *_NAME_FLAGS,502 required=False,503 type=str,504 default=None,505 help="[Optional] The name to pass to the sub-command (if applicable) If set again in the sub-command, "506 "the sub-command's parameter takes precedence.",507)508@_insecure_option509@_click.group("flyte-cli")510@_click.pass_context511def _flyte_cli(ctx, host, project, domain, name, insecure):512 """513 Command line tool for interacting with all entities on the Flyte Platform.514 """515 pass516########################################################################################################################517#518# Miscellaneous Commands519#520########################################################################################################################521@_flyte_cli.command("parse-proto", cls=_click.Command)522@_filename_option523@_idl_class_option524def parse_proto(filename, proto_class):525 _welcome_message()526 splitted = proto_class.split(".")527 idl_module = ".".join(splitted[:-1])528 idl_obj = splitted[-1]529 mod = _importlib.import_module(idl_module)530 idl = getattr(mod, idl_obj)531 obj = _load_proto_from_file(idl, filename)532 jsonObj = MessageToJson(obj)533 _click.echo(jsonObj)534 _click.echo("")535########################################################################################################################536#537# Task Commands538#539########################################################################################################################540@_flyte_cli.command("list-task-names", cls=_FlyteSubCommand)541@_project_option542@_domain_option543@_host_option544@_insecure_option545@_token_option546@_limit_option547@_show_all_option548@_sort_by_option549def list_task_names(project, domain, host, insecure, token, limit, show_all, sort_by):550 """551 List the name of the tasks that are in the registered workflow under552 a specific project and domain.553 """554 _welcome_message()555 client = _friendly_client.SynchronousFlyteClient(host, insecure=insecure)556 _click.echo("Task Names Found in {}:{}\n".format(_tt(project), _tt(domain)))557 while True:558 task_ids, next_token = client.list_task_ids_paginated(559 project,560 domain,561 limit=limit,562 token=token,563 sort_by=_admin_common.Sort.from_python_std(sort_by) if sort_by else None,564 )565 for t in task_ids:566 _click.echo("\t{}".format(_tt(t.name)))567 if show_all is not True:568 if next_token:569 _click.echo("Received next token: {}\n".format(next_token))570 break571 if not next_token:572 break573 token = next_token574 _click.echo("")575@_flyte_cli.command("list-task-versions", cls=_FlyteSubCommand)576@_project_option577@_domain_option578@_optional_name_option579@_host_option580@_insecure_option581@_token_option582@_limit_option583@_show_all_option584@_filter_option585@_sort_by_option586def list_task_versions(project, domain, name, host, insecure, token, limit, show_all, filter, sort_by):587 """588 List all the versions of the tasks under a specific {Project, Domain} tuple.589 If the name of a certain task is supplied, this command will list all the590 versions of that particular task (identifiable by {Project, Domain, Name}).591 """592 _welcome_message()593 client = _friendly_client.SynchronousFlyteClient(host, insecure=insecure)594 _click.echo("Task Versions Found for {}:{}:{}\n".format(_tt(project), _tt(domain), _tt(name or "*")))595 _click.echo("{:50} {:40}".format("Version", "Urn"))596 while True:597 task_list, next_token = client.list_tasks_paginated(598 _common_models.NamedEntityIdentifier(project, domain, name),599 limit=limit,600 token=token,601 filters=[_filters.Filter.from_python_std(f) for f in filter],602 sort_by=_admin_common.Sort.from_python_std(sort_by) if sort_by else None,603 )604 for t in task_list:605 _click.echo(606 "{:50} {:40}".format(607 _tt(t.id.version),608 _tt(_identifier.Identifier.promote_from_model(t.id)),609 )610 )611 if show_all is not True:612 if next_token:613 _click.echo("Received next token: {}\n".format(next_token))614 break615 if not next_token:616 break617 token = next_token618 _click.echo("")619@_flyte_cli.command("get-task", cls=_FlyteSubCommand)620@_urn_option621@_host_option622@_insecure_option623def get_task(urn, host, insecure):624 """625 Get the details of a certain version of a task identified by the URN of it.626 The URN of the versioned task is in the form of ``tsk:<project>:<domain>:<task_name>:<version>``.627 """628 _welcome_message()629 client = _friendly_client.SynchronousFlyteClient(host, insecure=insecure)630 t = client.get_task(_identifier.Identifier.from_python_std(urn))631 _click.echo(_tt(t))632 _click.echo("")633@_flyte_cli.command("launch-task", cls=_FlyteSubCommand)634@_project_option635@_domain_option636@_optional_name_option637@_assumable_iam_role_option638@_kubernetes_service_acct_option639@_host_option640@_insecure_option641@_urn_option642@_click.argument("task_args", nargs=-1, type=_click.UNPROCESSED)643def launch_task(project, domain, name, assumable_iam_role, kubernetes_service_account, host, insecure, urn, task_args):644 """645 Kick off a single task execution. Note that the {project, domain, name} specified in the command line646 will be for the execution. The project/domain for the task are specified in the urn.647 Use a -- to separate arguments to this cli, and arguments to the task.648 e.g.649 $ flyte-cli -h localhost:30081 -p flyteexamples -d development launch-task \650 -u tsk:flyteexamples:development:some-task:abc123 -- input=hi \651 other-input=123 moreinput=qwerty652 These arguments are then collected, and passed into the `task_args` variable as a Tuple[Text].653 Users should use the get-task command to ascertain the names of inputs to use.654 """655 _welcome_message()656 auth_role = _AuthRole(assumable_iam_role=assumable_iam_role, kubernetes_service_account=kubernetes_service_account)657 with _platform_config.URL.get_patcher(host), _platform_config.INSECURE.get_patcher(_tt(insecure)):658 task_id = _identifier.Identifier.from_python_std(urn)659 task = _tasks_common.SdkTask.fetch(task_id.project, task_id.domain, task_id.name, task_id.version)660 text_args = _parse_args_into_dict(task_args)661 inputs = {}662 for var_name, variable in _six.iteritems(task.interface.inputs):663 sdk_type = _type_helpers.get_sdk_type_from_literal_type(variable.type)664 if var_name in text_args and text_args[var_name] is not None:665 inputs[var_name] = sdk_type.from_string(text_args[var_name]).to_python_std()666 # TODO: Implement notification overrides667 # TODO: Implement label overrides668 # TODO: Implement annotation overrides669 execution = task.launch(project, domain, inputs=inputs, name=name, auth_role=auth_role)670 _click.secho("Launched execution: {}".format(_tt(execution.id)), fg="blue")671 _click.echo("")672########################################################################################################################673#674# Workflow Commands675#676########################################################################################################################677@_flyte_cli.command("list-workflow-names", cls=_FlyteSubCommand)678@_project_option679@_domain_option680@_host_option681@_insecure_option682@_token_option683@_limit_option684@_show_all_option685@_sort_by_option686def list_workflow_names(project, domain, host, insecure, token, limit, show_all, sort_by):687 """688 List the names of the workflows under a scope specified by ``{project, domain}``.689 """690 _welcome_message()691 client = _friendly_client.SynchronousFlyteClient(host, insecure=insecure)692 _click.echo("Workflow Names Found in {}:{}\n".format(_tt(project), _tt(domain)))693 while True:694 wf_ids, next_token = client.list_workflow_ids_paginated(695 project,696 domain,697 limit=limit,698 token=token,699 sort_by=_admin_common.Sort.from_python_std(sort_by) if sort_by else None,700 )701 for i in wf_ids:702 _click.echo("\t{}".format(_tt(i.name)))703 if show_all is not True:704 if next_token:705 _click.echo("Received next token: {}\n".format(next_token))706 break707 if not next_token:708 break709 token = next_token710 _click.echo("")711@_flyte_cli.command("list-workflow-versions", cls=_FlyteSubCommand)712@_project_option713@_domain_option714@_optional_name_option715@_host_option716@_insecure_option717@_token_option718@_limit_option719@_show_all_option720@_filter_option721@_sort_by_option722def list_workflow_versions(project, domain, name, host, insecure, token, limit, show_all, filter, sort_by):723 """724 List all the versions of the workflows under the scope specified by ``{project, domain}``.725 If the name of a a certain workflow is supplied, this command will list all the726 versions of that particular workflow (identifiable by ``{project, domain, name}``).727 """728 _welcome_message()729 client = _friendly_client.SynchronousFlyteClient(host, insecure=insecure)730 _click.echo("Workflow Versions Found for {}:{}:{}\n".format(_tt(project), _tt(domain), _tt(name or "*")))731 _click.echo("{:50} {:40}".format("Version", "Urn"))732 while True:733 wf_list, next_token = client.list_workflows_paginated(734 _common_models.NamedEntityIdentifier(project, domain, name),735 limit=limit,736 token=token,737 filters=[_filters.Filter.from_python_std(f) for f in filter],738 sort_by=_admin_common.Sort.from_python_std(sort_by) if sort_by else None,739 )740 for w in wf_list:741 _click.echo(742 "{:50} {:40}".format(743 _tt(w.id.version),744 _tt(_identifier.Identifier.promote_from_model(w.id)),745 )746 )747 if show_all is not True:748 if next_token:749 _click.echo("Received next token: {}\n".format(next_token))750 break751 if not next_token:752 break753 token = next_token754 _click.echo("")755@_flyte_cli.command("get-workflow", cls=_FlyteSubCommand)756@_urn_option757@_host_option758@_insecure_option759def get_workflow(urn, host, insecure):760 """761 Get the details of a certain version of a workflow identified by the URN in the form of762 ``wf:<project>:<domain>:<workflow_name>:<version>``763 """764 _welcome_message()765 client = _friendly_client.SynchronousFlyteClient(host, insecure=insecure)766 _click.echo(client.get_workflow(_identifier.Identifier.from_python_std(urn)))767 # TODO: Print workflow pretty768 _click.echo("")769########################################################################################################################770#771# Launch Plan Commands772#773########################################################################################################################774@_flyte_cli.command("list-launch-plan-names", cls=_FlyteSubCommand)775@_project_option776@_domain_option777@_host_option778@_insecure_option779@_token_option780@_limit_option781@_show_all_option782@_sort_by_option783def list_launch_plan_names(project, domain, host, insecure, token, limit, show_all, sort_by):784 """785 List the names of the launch plans under the scope specified by {project, domain}.786 """787 _welcome_message()788 client = _friendly_client.SynchronousFlyteClient(host, insecure=insecure)789 _click.echo("Launch Plan Names Found in {}:{}\n".format(_tt(project), _tt(domain)))790 while True:791 wf_ids, next_token = client.list_launch_plan_ids_paginated(792 project,793 domain,794 limit=limit,795 token=token,796 sort_by=_admin_common.Sort.from_python_std(sort_by) if sort_by else None,797 )798 for i in wf_ids:799 _click.echo("\t{}".format(_tt(i.name)))800 if show_all is not True:801 if next_token:802 _click.echo("Received next token: {}\n".format(next_token))803 break804 if not next_token:805 break806 token = next_token807 _click.echo("")808@_flyte_cli.command("list-active-launch-plans", cls=_FlyteSubCommand)809@_project_option810@_domain_option811@_host_option812@_insecure_option813@_token_option814@_limit_option815@_show_all_option816@_sort_by_option817@_optional_urns_only_option818def list_active_launch_plans(project, domain, host, insecure, token, limit, show_all, sort_by, urns_only):819 """820 List the information of all the active launch plans under the scope specified by {project, domain}.821 An active launch plan is a launch plan with an active schedule associated with it.822 """823 if not urns_only:824 _welcome_message()825 _click.echo("Active Launch Plan Found in {}:{}\n".format(_tt(project), _tt(domain)))826 _click.echo("{:30} {:50} {:80}".format("Schedule", "Version", "Urn"))827 client = _friendly_client.SynchronousFlyteClient(host, insecure=insecure)828 while True:829 active_lps, next_token = client.list_active_launch_plans_paginated(830 project,831 domain,832 limit=limit,833 token=token,834 sort_by=_admin_common.Sort.from_python_std(sort_by) if sort_by else None,835 )836 for lp in active_lps:837 if urns_only:838 _click.echo("{:80}".format(_tt(_identifier.Identifier.promote_from_model(lp.id))))839 else:840 _click.echo(841 "{:30} {:50} {:80}".format(842 _render_schedule_expr(lp),843 _tt(lp.id.version),844 _tt(_identifier.Identifier.promote_from_model(lp.id)),845 ),846 )847 if show_all is not True:848 if next_token and not urns_only:849 _click.echo("Received next token: {}\n".format(next_token))850 break851 if not next_token:852 break853 token = next_token854 if not urns_only:855 _click.echo("")856 return857@_flyte_cli.command("list-launch-plan-versions", cls=_FlyteSubCommand)858@_project_option859@_domain_option860@_optional_name_option861@_host_option862@_insecure_option863@_token_option864@_limit_option865@_show_all_option866@_filter_option867@_sort_by_option868@_optional_urns_only_option869def list_launch_plan_versions(870 project,871 domain,872 name,873 host,874 insecure,875 token,876 limit,877 show_all,878 filter,879 sort_by,880 urns_only,881):882 """883 List the versions of all the launch plans under the scope specified by {project, domain}.884 """885 if not urns_only:886 _welcome_message()887 _click.echo("Launch Plan Versions Found for {}:{}:{}\n".format(_tt(project), _tt(domain), _tt(name)))888 _click.echo("{:50} {:80} {:30} {:15}".format("Version", "Urn", "Schedule", "Schedule State"))889 client = _friendly_client.SynchronousFlyteClient(host, insecure=insecure)890 while True:891 lp_list, next_token = client.list_launch_plans_paginated(892 _common_models.NamedEntityIdentifier(project, domain, name),893 limit=limit,894 token=token,895 filters=[_filters.Filter.from_python_std(f) for f in filter],896 sort_by=_admin_common.Sort.from_python_std(sort_by) if sort_by else None,897 )898 for l in lp_list:899 if urns_only:900 _click.echo(_tt(_identifier.Identifier.promote_from_model(l.id)))901 else:902 _click.echo(903 "{:50} {:80} ".format(904 _tt(l.id.version),905 _tt(_identifier.Identifier.promote_from_model(l.id)),906 ),907 nl=False,908 )909 if l.spec.entity_metadata.schedule is not None and (910 l.spec.entity_metadata.schedule.cron_expression or l.spec.entity_metadata.schedule.rate911 ):912 _click.echo("{:30} ".format(_render_schedule_expr(l)), nl=False)913 _click.secho(914 _launch_plan.LaunchPlanState.enum_to_string(l.closure.state),915 fg="green" if l.closure.state == _launch_plan.LaunchPlanState.ACTIVE else None,916 )917 else:918 _click.echo()919 if show_all is not True:920 if next_token and not urns_only:921 _click.echo("Received next token: {}\n".format(next_token))922 break923 if not next_token:924 break925 token = next_token926 if not urns_only:927 _click.echo("")928@_flyte_cli.command("get-launch-plan", cls=_FlyteSubCommand)929@_urn_option930@_host_option931@_insecure_option932def get_launch_plan(urn, host, insecure):933 """934 Get the details of a certain launch plan identified by the URN of that launch plan.935 The URN of a launch plan is in the form of ``lp:<project>:<domain>:<launch_plan_name>:<version>``936 """937 _welcome_message()938 client = _friendly_client.SynchronousFlyteClient(host, insecure=insecure)939 _click.echo(_tt(client.get_launch_plan(_identifier.Identifier.from_python_std(urn))))940 # TODO: Print launch plan pretty941 _click.echo("")942@_flyte_cli.command("get-active-launch-plan", cls=_FlyteSubCommand)943@_project_option944@_domain_option945@_name_option946@_host_option947@_insecure_option948def get_active_launch_plan(project, domain, name, host, insecure):949 """950 List the versions of all the launch plans under the scope specified by {project, domain}.951 """952 _welcome_message()953 client = _friendly_client.SynchronousFlyteClient(host, insecure=insecure)954 lp = client.get_active_launch_plan(_common_models.NamedEntityIdentifier(project, domain, name))955 _click.echo("Active Launch Plan for {}:{}:{}\n".format(_tt(project), _tt(domain), _tt(name)))956 _click.echo(lp)957 _click.echo("")958@_flyte_cli.command("update-launch-plan", cls=_FlyteSubCommand)959@_state_choice960@_host_option961@_insecure_option962@_optional_urn_option963def update_launch_plan(state, host, insecure, urn=None):964 _welcome_message()965 if urn is None:966 try:967 # Examine whether the input is from the named pipe968 if _stat.S_ISFIFO(_os.fstat(0).st_mode):969 for line in _sys.stdin.readlines():970 _update_one_launch_plan(urn=line.rstrip(), host=host, insecure=insecure, state=state)971 else:972 # If the commandline parameter urn is not supplied, and neither973 # the input comes from a pipe, it means the user is not using974 # this command approperiately975 raise _click.UsageError('Missing option "-u" / "--urn" or missing pipe inputs')976 except KeyboardInterrupt:977 _sys.stdout.flush()978 else:979 _update_one_launch_plan(urn=urn, host=host, insecure=insecure, state=state)980@_flyte_cli.command("execute-launch-plan", cls=_FlyteSubCommand)981@_project_option982@_domain_option983@_optional_name_option984@_host_option985@_insecure_option986@_urn_option987@_principal_option988@_verbose_option989@_watch_option990@_click.argument("lp_args", nargs=-1, type=_click.UNPROCESSED)991def execute_launch_plan(project, domain, name, host, insecure, urn, principal, verbose, watch, lp_args):992 """993 Kick off a launch plan. Note that the {project, domain, name} specified in the command line994 will be for the execution. The project/domain for the launch plan are specified in the urn.995 Use a -- to separate arguments to this cli, and arguments to the launch plan.996 e.g.997 $ flyte-cli -h localhost:30081 -p flyteexamples -d development execute-launch-plan \998 --verbose --principal=sdk-demo999 -u lp:flyteexamples:development:some-workflow:abc123 -- input=hi \1000 other-input=123 moreinput=qwerty1001 These arguments are then collected, and passed into the `lp_args` variable as a Tuple[Text].1002 Users should use the get-launch-plan command to ascertain the names of inputs to use.1003 """1004 _welcome_message()1005 with _platform_config.URL.get_patcher(host), _platform_config.INSECURE.get_patcher(_tt(insecure)):1006 lp_id = _identifier.Identifier.from_python_std(urn)1007 lp = _launch_plan_common.SdkLaunchPlan.fetch(lp_id.project, lp_id.domain, lp_id.name, lp_id.version)1008 inputs = _construct_literal_map_from_parameter_map(lp.default_inputs, _parse_args_into_dict(lp_args))1009 # TODO: Implement notification overrides1010 # TODO: Implement label overrides1011 # TODO: Implement annotation overrides1012 execution = lp.launch_with_literals(project, domain, inputs, name=name)1013 _click.secho("Launched execution: {}".format(_tt(execution.id)), fg="blue")1014 _click.echo("")1015 if watch is True:1016 execution.wait_for_completion()1017########################################################################################################################1018#1019# Execution Commands1020#1021########################################################################################################################1022@_flyte_cli.command("watch-execution", cls=_FlyteSubCommand)1023@_host_option1024@_insecure_option1025@_urn_option1026def watch_execution(host, insecure, urn):1027 """1028 Wait for an execution to complete.1029 e.g.1030 $ flyte-cli -h localhost:30081 watch-execution -u ex:flyteexamples:development:abc1231031 """1032 _welcome_message()1033 client = _friendly_client.SynchronousFlyteClient(host, insecure=insecure)1034 ex_id = _identifier.WorkflowExecutionIdentifier.from_python_std(urn)1035 execution = _workflow_execution_common.SdkWorkflowExecution.promote_from_model(client.get_execution(ex_id))1036 _click.echo("Waiting for the execution {} to complete ...".format(_tt(execution.id)))1037 with _platform_config.URL.get_patcher(host), _platform_config.INSECURE.get_patcher(_tt(insecure)):1038 execution.wait_for_completion()1039@_flyte_cli.command("relaunch-execution", cls=_FlyteSubCommand)1040@_optional_project_option1041@_optional_domain_option1042@_optional_name_option1043@_host_option1044@_insecure_option1045@_urn_option1046@_optional_principal_option1047@_verbose_option1048@_click.argument("lp_args", nargs=-1, type=_click.UNPROCESSED)1049def relaunch_execution(project, domain, name, host, insecure, urn, principal, verbose, lp_args):1050 """1051 Relaunch a launch plan.1052 As with kicking off a launch plan (see execute-launch-plan), the project and domain will correspond to the new1053 execution to be run, and the project/domain used to find the existing execution will come from the URN.1054 This means you can re-run a development execution, in production, off of a staging launch-plan (in another project),1055 but beware that execution environment configurations can result in slower executions or permissions failures.1056 Therefore, it is recommended to re-run in the same environment as the original execution. By default, if the1057 project and domain are not specified, the existing project/domain will be used.1058 When relaunching an execution, this will display the fixed inputs that it ran with (from the launch plan spec),1059 and handle the other inputs similar to how we handle initial launch plan execution, except that1060 all inputs now will have a default (the input of the execution being rerun).1061 Use a -- to separate arguments to this cli, and arguments to the launch plan.1062 e.g.1063 $ flyte-cli -h localhost:30081 -p flyteexamples -d development execute-launch-plan \1064 -u lp:flyteexamples:development:some-workflow:abc123 -- input=hi \1065 other-input=123 moreinput=qwerty1066 These arguments are then collected, and passed into the `lp_args` variable as a Tuple[Text].1067 Users should use the get-execution and get-launch-plan commands to ascertain the names of inputs to use.1068 """1069 _welcome_message()1070 client = _friendly_client.SynchronousFlyteClient(host, insecure=insecure)1071 _click.echo("Relaunching execution {}\n".format(_tt(urn)))1072 existing_workflow_execution_identifier = _identifier.WorkflowExecutionIdentifier.from_python_std(urn)1073 e = client.get_execution(existing_workflow_execution_identifier)1074 if project is None:1075 project = existing_workflow_execution_identifier.project1076 if domain is None:1077 domain = existing_workflow_execution_identifier.domain1078 if principal is None:1079 principal = e.spec.metadata.principal1080 lp_model = client.get_launch_plan(e.spec.launch_plan)1081 expected_inputs = lp_model.closure.expected_inputs1082 # Parse text inputs using the LP closure's parameter map to determine types. However, since all inputs are now1083 # optional (because we can default to the original execution's), we reduce first to bare Variables.1084 variable_map = {k: v.var for k, v in _six.iteritems(expected_inputs.parameters)}1085 parsed_text_args = _parse_args_into_dict(lp_args)1086 new_inputs = _construct_literal_map_from_variable_map(variable_map, parsed_text_args)1087 if len(new_inputs.literals) > 0:1088 _click.secho("\tNew Inputs: {}\n".format(_prefix_lines("\t\t", _get_io_string(new_inputs, verbose=verbose))))1089 # Construct new inputs from existing execution inputs and new inputs1090 inputs_dict = {}1091 for k in e.spec.inputs.literals.keys():1092 if k in new_inputs.literals:1093 inputs_dict[k] = new_inputs.literals[k]1094 else:1095 inputs_dict[k] = e.spec.inputs.literals[k]1096 inputs = _literals.LiteralMap(literals=inputs_dict)1097 if len(inputs_dict) > 0:1098 _click.secho(1099 "\tFinal Inputs for New Execution: {}\n".format(1100 _prefix_lines("\t\t", _get_io_string(inputs, verbose=verbose))1101 )1102 )1103 metadata = _ExecutionMetadata(mode=_ExecutionMetadata.ExecutionMode.MANUAL, principal=principal, nesting=0)1104 ex_spec = _ExecutionSpec(launch_plan=lp_model.id, inputs=inputs, metadata=metadata)1105 execution_identifier = client.create_execution(project=project, domain=domain, name=name, execution_spec=ex_spec)1106 execution_identifier = _identifier.WorkflowExecutionIdentifier.promote_from_model(execution_identifier)1107 _click.secho("Launched execution: {}".format(execution_identifier), fg="blue")1108 _click.echo("")1109@_flyte_cli.command("recover-execution", cls=_FlyteSubCommand)1110@_urn_option1111@_optional_name_option1112@_host_option1113@_insecure_option1114def recover_execution(urn, name, host, insecure):1115 """1116 Recreates a previously-run workflow execution that will only start executing from the last known failure point.1117 In Recover mode, users cannot change any input parameters or update the version of the execution.1118 This is extremely useful to recover from system errors and byzantine faults like1119 - loss of K8s cluster1120 - bugs in platform or instability1121 - machine failures1122 - downstream system failures (downstream services)1123 - or simply to recover executions that failed because of retry exhaustion and should complete if tried again.1124 You can optionally assign a name to the recreated execution you trigger or let the system assing one.1125 Usage:1126 $ flyte-cli recover-execution -u ex:flyteexamples:development:some-workflow:abc123 -n my_retry_name1127 These arguments are then collected, and passed into the `lp_args` variable as a Tuple[Text].1128 Users should use the get-execution and get-launch-plan commands to ascertain the names of inputs to use.1129 """1130 _welcome_message()1131 client = _friendly_client.SynchronousFlyteClient(host, insecure=insecure)1132 _click.echo("Recovering execution {}\n".format(_tt(urn)))1133 original_workflow_execution_identifier = _identifier.WorkflowExecutionIdentifier.from_python_std(urn)1134 execution_identifier_resp = client.recover_execution(id=original_workflow_execution_identifier, name=name)1135 execution_identifier = _identifier.WorkflowExecutionIdentifier.promote_from_model(execution_identifier_resp)1136 _click.secho("Launched execution: {}".format(execution_identifier), fg="blue")1137 _click.echo("")1138@_flyte_cli.command("terminate-execution", cls=_FlyteSubCommand)1139@_host_option1140@_insecure_option1141@_cause_option1142@_optional_urn_option1143def terminate_execution(host, insecure, cause, urn=None):1144 """1145 Terminate an execution or a list of executions. This command terminates an execution1146 specified by the URN. It can only terminate the executions the status of which are "RUNNING".1147 The post-termination status of those executions will become "ABORTED".1148 When terminating an execution, the cause of termination is a required input.1149 This command also supports batch terminating multiple executions at a time, which can be1150 achieved by supplying multiple URNs via the named pipe.1151 Note that, the termination of executions might not take immediate effect, as the1152 FlyteCLI only sends a termination request to FlyteAdmin. The actual termination1153 of the execution(s) depends on many other factors such as the status of the1154 machine serving the execution, etc.1155 e.g.,1156 $ flyte-cli -h localhost:30081 -p flyteexamples -d development terminate-execution \1157 -u lp:flyteexamples:development:some-execution:abc1231158 """1159 _welcome_message()1160 client = _friendly_client.SynchronousFlyteClient(host, insecure=insecure)1161 _click.echo("Killing the following executions:\n")1162 _click.echo("{:100} {:40}".format("Urn", "Cause"))1163 # It first collects the urns in a list, and then send terminate request1164 # for them one-by-one1165 if urn is None:1166 try:1167 # Examine whether the input is from FIFO (named pipe)1168 if _stat.S_ISFIFO(_os.fstat(0).st_mode):1169 for line in _sys.stdin.readlines():1170 _terminate_one_execution(client, line.rstrip(), cause)1171 else:1172 # If the commandline parameter urn is not supplied, and neither1173 # the input is from a pipe, it means the user is not using1174 # this command appropriately1175 raise _click.UsageError('Missing option "-u" / "--urn" or missing pipe inputs.')1176 except KeyboardInterrupt:1177 _sys.stdout.flush()1178 pass1179 else:1180 _terminate_one_execution(client, urn, cause)1181@_flyte_cli.command("list-executions", cls=_FlyteSubCommand)1182@_project_option1183@_domain_option1184@_host_option1185@_insecure_option1186@_token_option1187@_limit_option1188@_show_all_option1189@_filter_option1190@_sort_by_option1191@_optional_urns_only_option1192def list_executions(project, domain, host, insecure, token, limit, show_all, filter, sort_by, urns_only):1193 """1194 List the key information of all the executions under the scope specified by {project, domain}.1195 Users can supply additional filter arguments to show only the desired exeuctions.1196 Note that, when the ``--urns-only`` flag is not set, this command prints out the complete tabular1197 output with key pieces of information such as the URN, the Name and the Status of the executions;1198 the column headers are also printed. If the flag is set, on the other hand, only the URNs1199 of the executions will be printed. This will come in handy when the user wants to, for example, terminate all the1200 running executions at once.1201 """1202 if not urns_only:1203 _welcome_message()1204 _click.echo("Executions Found in {}:{}\n".format(_tt(project), _tt(domain)))1205 _click.echo("{:100} {:40} {:10}".format("Urn", "Name", "Status"))1206 client = _friendly_client.SynchronousFlyteClient(host, insecure=insecure)1207 while True:1208 exec_ids, next_token = client.list_executions_paginated(1209 project,1210 domain,1211 limit=limit,1212 token=token,1213 filters=[_filters.Filter.from_python_std(f) for f in filter],1214 sort_by=_admin_common.Sort.from_python_std(sort_by) if sort_by else None,1215 )1216 for ex in exec_ids:1217 _secho_one_execution(ex, urns_only)1218 if show_all is not True:1219 if next_token and not urns_only:1220 _click.echo("Received next token: {}\n".format(next_token))1221 break1222 if not next_token:1223 break1224 token = next_token1225 if not urns_only:1226 _click.echo("")1227def _get_io(node_executions, wf_execution, show_io, verbose):1228 # Fetch I/O if necessary1229 uri_to_message_map = {}1230 if show_io:1231 uris = [ne.input_uri for ne in node_executions]1232 uris.extend([ne.closure.output_uri for ne in node_executions if ne.closure.output_uri is not None])1233 if (1234 wf_execution is not None1235 and wf_execution.closure.outputs is not None1236 and wf_execution.closure.outputs.uri is not None1237 ):1238 uris.append(wf_execution.closure.outputs.uri)1239 with _click.progressbar(uris, label="Downloading Inputs and Outputs") as progress_bar_uris:1240 for uri in progress_bar_uris:1241 uri_to_message_map[uri] = _fetch_and_stringify_literal_map(uri, verbose=verbose)1242 return uri_to_message_map1243def _render_workflow_execution(wf_execution, uri_to_message_map, show_io, verbose):1244 _click.echo(1245 "\nExecution {project}:{domain}:{name}\n".format(1246 project=_tt(wf_execution.id.project),1247 domain=_tt(wf_execution.id.domain),1248 name=_tt(wf_execution.id.name),1249 )1250 )1251 _click.echo("\t{:15} ".format("State:"), nl=False)1252 _secho_workflow_status(wf_execution.closure.phase)1253 _click.echo(1254 "\t{:15} {}".format(1255 "Launch Plan:",1256 _tt(_identifier.Identifier.promote_from_model(wf_execution.spec.launch_plan)),1257 )1258 )1259 if show_io:1260 _click.secho(1261 "\tInputs: {}\n".format(1262 _prefix_lines(1263 "\t\t",1264 _get_io_string(wf_execution.closure.computed_inputs, verbose=verbose),1265 )1266 )1267 )1268 if wf_execution.closure.outputs is not None:1269 if wf_execution.closure.outputs.uri:1270 _click.secho(1271 "\tOutputs: {}\n".format(1272 _prefix_lines(1273 "\t\t",1274 uri_to_message_map.get(1275 wf_execution.closure.outputs.uri,1276 wf_execution.closure.outputs.uri,1277 ),1278 )1279 )1280 )1281 elif wf_execution.closure.outputs.values is not None:1282 _click.secho(1283 "\tOutputs: {}\n".format(1284 _prefix_lines(1285 "\t\t",1286 _get_io_string(wf_execution.closure.outputs.values, verbose=verbose),1287 )1288 )1289 )1290 else:1291 _click.echo("\t{:15} (None)".format("Outputs:"))1292 if wf_execution.closure.error is not None:1293 _click.secho(1294 _prefix_lines("\t", _render_error(wf_execution.closure.error)),1295 fg="red",1296 bold=True,1297 )1298def _render_error(error):1299 out = "Error:\n"1300 out += "\tCode: {}\n".format(error.code)1301 out += "\tMessage:\n"1302 for l in error.message.splitlines():1303 out += "\t\t{}".format(_tt(l))1304 return out1305def _get_all_task_executions_for_node(client, node_execution_identifier):1306 fetched_task_execs = []1307 token = ""1308 while True:1309 num_to_fetch = 1001310 task_execs, next_token = client.list_task_executions_paginated(1311 node_execution_identifier=node_execution_identifier,1312 limit=num_to_fetch,1313 token=token,1314 )1315 for te in task_execs:1316 fetched_task_execs.append(te)1317 if not next_token:1318 break1319 token = next_token1320 return fetched_task_execs1321def _get_all_node_executions(client, workflow_execution_identifier=None, task_execution_identifier=None):1322 all_node_execs = []1323 token = ""1324 while True:1325 num_to_fetch = 1001326 if workflow_execution_identifier:1327 node_execs, next_token = client.list_node_executions(1328 workflow_execution_identifier=workflow_execution_identifier,1329 limit=num_to_fetch,1330 token=token,1331 )1332 else:1333 node_execs, next_token = client.list_node_executions_for_task_paginated(1334 task_execution_identifier=task_execution_identifier,1335 limit=num_to_fetch,1336 token=token,1337 )1338 all_node_execs.extend(node_execs)1339 if not next_token:1340 break1341 token = next_token1342 return all_node_execs1343def _render_node_executions(client, node_execs, show_io, verbose, host, insecure, wf_execution=None):1344 node_executions_to_task_executions = {}1345 for node_exec in node_execs:1346 node_executions_to_task_executions[node_exec.id] = _get_all_task_executions_for_node(client, node_exec.id)1347 uri_to_message_map = _get_io(node_execs, wf_execution, show_io, verbose)1348 if wf_execution is not None:1349 _render_workflow_execution(wf_execution, uri_to_message_map, show_io, verbose)1350 _click.echo("\n\tNode Executions:\n")1351 for ne in sorted(node_execs, key=lambda x: x.closure.started_at):1352 if ne.id.node_id == "start-node":1353 continue1354 _click.echo("\t\tID: {}\n".format(_tt(ne.id.node_id)))1355 _click.echo("\t\t\t{:15} ".format("Status:"), nl=False)1356 _secho_node_execution_status(ne.closure.phase)1357 _click.echo("\t\t\t{:15} {:60} ".format("Started:", _tt(ne.closure.started_at)))1358 _click.echo("\t\t\t{:15} {:60} ".format("Duration:", _tt(ne.closure.duration)))1359 _click.echo(1360 "\t\t\t{:15} {}".format(1361 "Input:",1362 _prefix_lines(1363 "\t\t\t{:15} ".format(""),1364 uri_to_message_map.get(ne.input_uri, ne.input_uri),1365 ),1366 )1367 )1368 if ne.closure.output_uri:1369 _click.echo(1370 "\t\t\t{:15} {}".format(1371 "Output:",1372 _prefix_lines(1373 "\t\t\t{:15} ".format(""),1374 uri_to_message_map.get(ne.closure.output_uri, ne.closure.output_uri),1375 ),1376 )1377 )1378 if ne.closure.error is not None:1379 _click.secho(1380 _prefix_lines("\t\t\t", _render_error(ne.closure.error)),1381 bold=True,1382 fg="red",1383 )1384 task_executions = node_executions_to_task_executions.get(ne.id, [])1385 if len(task_executions) > 0:1386 _click.echo("\n\t\t\tTask Executions:\n")1387 for te in sorted(task_executions, key=lambda x: x.id.retry_attempt):1388 _click.echo("\t\t\t\tAttempt {}:\n".format(te.id.retry_attempt))1389 _click.echo("\t\t\t\t\t{:15} {:60} ".format("Created:", _tt(te.closure.created_at)))1390 _click.echo("\t\t\t\t\t{:15} {:60} ".format("Started:", _tt(te.closure.started_at)))1391 _click.echo("\t\t\t\t\t{:15} {:60} ".format("Updated:", _tt(te.closure.updated_at)))1392 _click.echo("\t\t\t\t\t{:15} {:60} ".format("Duration:", _tt(te.closure.duration)))1393 _click.echo("\t\t\t\t\t{:15} ".format("Status:"), nl=False)1394 _secho_task_execution_status(te.closure.phase)1395 if len(te.closure.logs) == 0:1396 _click.echo("\t\t\t\t\t{:15} {:60} ".format("Logs:", "(None Found Yet)"))1397 else:1398 _click.echo("\t\t\t\t\tLogs:\n")1399 for log in sorted(te.closure.logs, key=lambda x: x.name):1400 _click.echo("\t\t\t\t\t\t{:8} {}".format("Name:", log.name))1401 _click.echo("\t\t\t\t\t\t{:8} {}\n".format("URI:", log.uri))1402 if te.closure.error is not None:1403 _click.secho(1404 _prefix_lines("\t\t\t\t\t", _render_error(te.closure.error)),1405 bold=True,1406 fg="red",1407 )1408 if te.is_parent:1409 _click.echo(1410 "\t\t\t\t\t{:15} {:60} ".format(1411 "Subtasks:",1412 "flyte-cli get-child-executions -h {host}{insecure} -u {urn}".format(1413 host=host,1414 urn=_tt(_identifier.TaskExecutionIdentifier.promote_from_model(te.id)),1415 insecure=" --insecure" if insecure else "",1416 ),1417 )1418 )1419 _click.echo()1420 _click.echo()1421 _click.echo()1422@_flyte_cli.command("get-execution", cls=_FlyteSubCommand)1423@_urn_option1424@_host_option1425@_insecure_option1426@_show_io_option1427@_verbose_option1428def get_execution(urn, host, insecure, show_io, verbose):1429 """1430 Get the detail information of a certain execution identified by the URN of that launch plan.1431 The URN of an execution is in the form of ``ex:<project>:<domain>:<execution_name>``1432 """1433 _welcome_message()1434 client = _friendly_client.SynchronousFlyteClient(host, insecure=insecure)1435 e = client.get_execution(_identifier.WorkflowExecutionIdentifier.from_python_std(urn))1436 node_execs = _get_all_node_executions(client, workflow_execution_identifier=e.id)1437 _render_node_executions(client, node_execs, show_io, verbose, host, insecure, wf_execution=e)1438@_flyte_cli.command("get-child-executions", cls=_FlyteSubCommand)1439@_urn_option1440@_host_option1441@_insecure_option1442@_show_io_option1443@_verbose_option1444def get_child_executions(urn, host, insecure, show_io, verbose):1445 _welcome_message()1446 client = _friendly_client.SynchronousFlyteClient(host, insecure=insecure)1447 node_execs = _get_all_node_executions(1448 client,1449 task_execution_identifier=_identifier.TaskExecutionIdentifier.from_python_std(urn),1450 )1451 _render_node_executions(client, node_execs, show_io, verbose, host, insecure)1452@_flyte_cli.command("register-project", cls=_FlyteSubCommand)1453@_project_identifier_option1454@_project_name_option1455@_project_description_option1456@_host_option1457@_insecure_option1458def register_project(identifier, name, description, host, insecure):1459 """1460 Register a new project.1461 """1462 _welcome_message()1463 client = _friendly_client.SynchronousFlyteClient(host, insecure=insecure)1464 client.register_project(_Project(identifier, name, description))1465 _click.echo("Registered project [id: {}, name: {}, description: {}]".format(identifier, name, description))1466@_flyte_cli.command("list-projects", cls=_FlyteSubCommand)1467@_host_option1468@_insecure_option1469@_token_option1470@_limit_option1471@_show_all_option1472@_filter_option1473@_sort_by_option1474def list_projects(host, insecure, token, limit, show_all, filter, sort_by):1475 """1476 List projects.1477 """1478 _welcome_message()1479 client = _friendly_client.SynchronousFlyteClient(host, insecure=insecure)1480 _click.echo("Projects Found\n")1481 while True:1482 projects, next_token = client.list_projects_paginated(1483 limit=limit,1484 token=token,1485 filters=[_filters.Filter.from_python_std(f) for f in filter],1486 sort_by=_admin_common.Sort.from_python_std(sort_by) if sort_by else None,1487 )1488 for p in projects:1489 _click.echo("\t{}".format(_tt(p.id)))1490 if show_all is not True:1491 if next_token:1492 _click.echo("Received next token: {}\n".format(next_token))1493 break1494 if not next_token:1495 break1496 token = next_token1497 _click.echo("")1498@_flyte_cli.command("archive-project", cls=_FlyteSubCommand)1499@_project_identifier_option1500@_host_option1501@_insecure_option1502def archive_project(identifier, host, insecure):1503 """1504 Archive a project.1505 """1506 _welcome_message()1507 client = _friendly_client.SynchronousFlyteClient(host, insecure=insecure)1508 client.update_project(_Project.archived_project(identifier))1509 _click.echo("Archived project [id: {}]".format(identifier))1510@_flyte_cli.command("activate-project", cls=_FlyteSubCommand)1511@_project_identifier_option1512@_host_option1513@_insecure_option1514def activate_project(identifier, host, insecure):1515 """1516 Activate a project.1517 """1518 _welcome_message()1519 client = _friendly_client.SynchronousFlyteClient(host, insecure=insecure)1520 client.update_project(_Project.active_project(identifier))1521 _click.echo("Activated project [id: {}]".format(identifier))1522_resource_map = {1523 _identifier_pb2.LAUNCH_PLAN: _launch_plan_pb2.LaunchPlan,1524 _identifier_pb2.WORKFLOW: _workflow_pb2.WorkflowSpec,1525 _identifier_pb2.TASK: _task_pb2.TaskSpec,1526}1527def _extract_pair(1528 object_file: str,1529 resource_type: int,1530 project: str,1531 domain: str,1532 version: str,1533 patches: Dict[int, Callable[[_GeneratedProtocolMessageType], _GeneratedProtocolMessageType]],1534) -> Tuple[1535 _identifier_pb2.Identifier,1536 Union[_core_tasks_pb2.TaskTemplate, _core_workflow_pb2.WorkflowTemplate, _launch_plan_pb2.LaunchPlanSpec],1537]:1538 """1539 :param Text identifier_file:1540 :param Text object_file:1541 :rtype: (flyteidl.core.identifier_pb2.Identifier, T)1542 """1543 if resource_type not in _resource_map:1544 raise _user_exceptions.FlyteAssertion(1545 f"Resource type found in proto file name [{resource_type}] invalid, "1546 "must be 1 (task), 2 (workflow) or 3 (launch plan)"1547 )1548 entity = _load_proto_from_file(_resource_map[resource_type], object_file)1549 registerable_identifier, registerable_entity = hydrate_registration_parameters(1550 resource_type, project, domain, version, entity1551 )1552 patch_fn = patches.get(resource_type)1553 if patch_fn:1554 registerable_entity = patch_fn(registerable_entity)1555 return registerable_identifier, registerable_entity1556def _extract_files(1557 project: str,1558 domain: str,1559 version: str,1560 file_paths: List[str],1561 patches: Dict[int, Callable[[_GeneratedProtocolMessageType], _GeneratedProtocolMessageType]] = None,1562):1563 """1564 :param file_paths:1565 :rtype: List[(flyteidl.core.identifier_pb2.Identifier, T)]1566 """1567 # Get a manual iterator because we're going to grab files two at a time.1568 # The identifier file will always come first because the names are always the same and .identifier.pb sorts before1569 # .pb1570 results = []1571 for proto_file in file_paths:1572 # Serialized proto files are of the form: 12_foo.bar_1.pb1573 # Where 12 indicates it is the 12 file to process in order and 1 that is of resource type 1, or TASK.1574 resource_type = int(proto_file[-4])1575 id, entity = _extract_pair(proto_file, resource_type, project, domain, version, patches or {})1576 results.append((id, entity))1577 return results1578def _get_patch_launch_plan_fn(1579 assumable_iam_role: str = None, kubernetes_service_account: str = None, output_location_prefix: str = None1580) -> Callable[[_GeneratedProtocolMessageType], _GeneratedProtocolMessageType]:1581 def patch_launch_plan(entity: _GeneratedProtocolMessageType) -> _GeneratedProtocolMessageType:1582 """1583 Updates launch plans during registration to add a customizable auth role that overrides any values set in1584 the flyte config and/or a custom output_location_prefix.1585 """1586 # entity is of type flyteidl.admin.launch_plan_pb2.LaunchPlanSpec1587 auth_assumable_iam_role = (1588 assumable_iam_role if assumable_iam_role is not None else _auth_config.ASSUMABLE_IAM_ROLE.get()1589 )1590 auth_k8s_service_account = (1591 kubernetes_service_account1592 if kubernetes_service_account is not None1593 else _auth_config.KUBERNETES_SERVICE_ACCOUNT.get()1594 )1595 entity.spec.auth_role.CopyFrom(1596 _AuthRole(1597 assumable_iam_role=auth_assumable_iam_role, kubernetes_service_account=auth_k8s_service_account1598 ).to_flyte_idl(),1599 )1600 if output_location_prefix is not None:1601 entity.spec.raw_output_data_config.CopyFrom(1602 _RawOutputDataConfig(output_location_prefix=output_location_prefix).to_flyte_idl()1603 )1604 elif _auth_config.RAW_OUTPUT_DATA_PREFIX.get() is not None:1605 entity.spec.raw_output_data_config.CopyFrom(1606 _RawOutputDataConfig(output_location_prefix=_auth_config.RAW_OUTPUT_DATA_PREFIX.get()).to_flyte_idl()1607 )1608 return entity1609 return patch_launch_plan1610def _extract_and_register(1611 host: str,1612 insecure: bool,1613 project: str,1614 domain: str,1615 version: str,1616 file_paths: List[str],1617 patches: Dict[int, Callable[[_GeneratedProtocolMessageType], _GeneratedProtocolMessageType]] = None,1618):1619 client = _friendly_client.SynchronousFlyteClient(host, insecure=insecure)1620 flyte_entities_list = _extract_files(project, domain, version, file_paths, patches)1621 for id, flyte_entity in flyte_entities_list:1622 _click.secho(f"Registering {id}", fg="yellow")1623 try:1624 if id.resource_type == _identifier_pb2.LAUNCH_PLAN:1625 client.raw.create_launch_plan(_launch_plan_pb2.LaunchPlanCreateRequest(id=id, spec=flyte_entity.spec))1626 elif id.resource_type == _identifier_pb2.TASK:1627 client.raw.create_task(_task_pb2.TaskCreateRequest(id=id, spec=flyte_entity))1628 elif id.resource_type == _identifier_pb2.WORKFLOW:1629 client.raw.create_workflow(_workflow_pb2.WorkflowCreateRequest(id=id, spec=flyte_entity))1630 else:1631 raise _user_exceptions.FlyteAssertion(1632 f"Only tasks, launch plans, and workflows can be called with this function, "1633 f"resource type {id.resource_type} was passed"1634 )1635 except _user_exceptions.FlyteEntityAlreadyExistsException:1636 _click.secho(f"Skipping because already registered {id}", fg="cyan")1637 _click.echo(f"Finished scanning {len(flyte_entities_list)} files")1638@_flyte_cli.command("register-files", cls=_FlyteSubCommand)1639@_click.option(*_PROJECT_FLAGS, required=True, help="The project namespace to register with.")1640@_click.option(*_DOMAIN_FLAGS, required=True, help="The domain namespace to register with.")1641@_click.option(*_VERSION_FLAGS, required=True, help="The entity version to register with")1642@_host_option1643@_insecure_option1644@_assumable_iam_role_option1645@_kubernetes_service_acct_option1646@_output_location_prefix_option1647@_files_argument1648def register_files(1649 project,1650 domain,1651 version,1652 host,1653 insecure,1654 assumable_iam_role,1655 kubernetes_service_account,1656 output_location_prefix,1657 files,1658):1659 """1660 Given a list of files, this will (after sorting the input list), attempt to register them against Flyte Admin.1661 This command expects the files to be the output of the pyflyte serialize command. See the code there for more1662 information. Valid files need to be:\n1663 * Ordered in the order that you want registration to happen. pyflyte should have done the topological sort1664 for you and produced file that have a prefix that sets the correct order.\n1665 * Of the correct type. That is, they should be the serialized form of one of these Flyte IDL objects1666 (or an identifier object).\n1667 - flyteidl.admin.launch_plan_pb2.LaunchPlan for launch plans\n1668 - flyteidl.admin.workflow_pb2.WorkflowSpec for workflows\n1669 - flyteidl.admin.task_pb2.TaskSpec for tasks\n1670 :param host:1671 :param insecure:1672 :param files:1673 :return:1674 """1675 _welcome_message()1676 files = list(files)1677 files.sort()1678 _click.secho("Parsing files...", fg="green", bold=True)1679 for f in files:1680 _click.echo(f" {f}")1681 patches = {1682 _identifier_pb2.LAUNCH_PLAN: _get_patch_launch_plan_fn(1683 assumable_iam_role, kubernetes_service_account, output_location_prefix1684 )1685 }1686 _extract_and_register(host, insecure, project, domain, version, files, patches)1687@_flyte_cli.command("fast-register-files", cls=_FlyteSubCommand)1688@_click.option(*_PROJECT_FLAGS, required=True, help="The project namespace to register with.")1689@_click.option(*_DOMAIN_FLAGS, required=True, help="The domain namespace to register with.")1690@_click.option(1691 *_VERSION_FLAGS,1692 required=False,1693 help="Version to register entities with. This is normally computed deterministically from your code, but you can "1694 "override that here",1695)1696@_host_option1697@_insecure_option1698@_click.option("--additional-distribution-dir", required=True, help="Location for additional distributions")1699@_click.option(1700 "--dest-dir",1701 type=str,1702 help="[Optional] The output directory for code which is downloaded during fast registration, "1703 "if the current working directory at the time of installation is not desired",1704)1705@_assumable_iam_role_option1706@_kubernetes_service_acct_option1707@_output_location_prefix_option1708@_files_argument1709def fast_register_files(1710 project,1711 domain,1712 version,1713 host,1714 insecure,1715 additional_distribution_dir,1716 dest_dir,1717 assumable_iam_role,1718 kubernetes_service_account,1719 output_location_prefix,1720 files,1721):1722 """1723 Given a list of files, this will (after sorting the input list), attempt to register them against Flyte Admin.1724 This command expects the files to be the output of the pyflyte serialize command. See the code there for more1725 information. Valid files need to be:\n1726 * Ordered in the order that you want registration to happen. pyflyte should have done the topological sort1727 for you and produced file that have a prefix that sets the correct order.\n1728 * Of the correct type. That is, they should be the serialized form of one of these Flyte IDL objects1729 (or an identifier object).\n1730 - flyteidl.admin.launch_plan_pb2.LaunchPlanSpec for launch plans\n1731 - flyteidl.admin.workflow_pb2.WorkflowSpec for workflows\n1732 - flyteidl.admin.task_pb2.TaskSpec for tasks\n1733 :param host:1734 :param insecure:1735 :param files:1736 :return:1737 """1738 _welcome_message()1739 files = list(files)1740 files.sort()1741 _click.secho("Parsing files...", fg="green", bold=True)1742 compressed_source, digest = None, None1743 pb_files = []1744 for f in files:1745 if f.endswith("tar.gz"):1746 compressed_source = f1747 digest = os.path.basename(f).split(".")[0]1748 else:1749 _click.echo(f" {f}")1750 pb_files.append(f)1751 if compressed_source is None:1752 raise _click.UsageError(1753 "Could not discover compressed source, did you remember to run `pyflyte serialize fast ...`?"1754 )1755 version = version if version else digest1756 full_remote_path = _get_additional_distribution_loc(additional_distribution_dir, version)1757 Data.put_data(compressed_source, full_remote_path)1758 _click.secho(f"Uploaded compressed code archive {compressed_source} to {full_remote_path}", fg="green")1759 def fast_register_task(entity: _GeneratedProtocolMessageType) -> _GeneratedProtocolMessageType:1760 """1761 Updates task definitions during fast-registration in order to use the compatible pyflyte fast execute command at1762 task execution.1763 """1764 # entity is of type flyteidl.admin.task_pb2.TaskSpec1765 if not entity.template.HasField("container") or len(entity.template.container.args) == 0:1766 # Containerless tasks are always fast registerable without modification1767 return entity1768 complete_args = []1769 for arg in entity.template.container.args:1770 if arg == "{{ .remote_package_path }}":1771 arg = full_remote_path1772 elif arg == "{{ .dest_dir }}":1773 arg = dest_dir if dest_dir else "."1774 complete_args.append(arg)1775 del entity.template.container.args[:]1776 entity.template.container.args.extend(complete_args)1777 return entity1778 patches = {1779 _identifier_pb2.TASK: fast_register_task,1780 _identifier_pb2.LAUNCH_PLAN: _get_patch_launch_plan_fn(1781 assumable_iam_role, kubernetes_service_account, output_location_prefix1782 ),1783 }1784 _extract_and_register(host, insecure, project, domain, version, pb_files, patches)1785@_flyte_cli.command("update-workflow-meta", cls=_FlyteSubCommand)1786@_named_entity_description_option1787@_named_entity_state_choice1788@_host_option1789@_insecure_option1790@_project_option1791@_domain_option1792@_optional_name_option1793def update_workflow_meta(description, state, host, insecure, project, domain, name):1794 """1795 Updates a workflow entity under the scope specified by {project, domain, name} across versions.1796 """1797 _welcome_message()1798 client = _friendly_client.SynchronousFlyteClient(host, insecure=insecure)1799 if state == "active":1800 state = _named_entity.NamedEntityState.ACTIVE1801 elif state == "archived":1802 state = _named_entity.NamedEntityState.ARCHIVED1803 client.update_named_entity(1804 _core_identifier.ResourceType.WORKFLOW,1805 _named_entity.NamedEntityIdentifier(project, domain, name),1806 _named_entity.NamedEntityMetadata(description, state),1807 )1808 _click.echo("Successfully updated workflow")1809@_flyte_cli.command("update-task-meta", cls=_FlyteSubCommand)1810@_named_entity_description_option1811@_host_option1812@_insecure_option1813@_project_option1814@_domain_option1815@_optional_name_option1816def update_task_meta(description, host, insecure, project, domain, name):1817 """1818 Updates a task entity under the scope specified by {project, domain, name} across versions.1819 """1820 _welcome_message()1821 client = _friendly_client.SynchronousFlyteClient(host, insecure=insecure)1822 client.update_named_entity(1823 _core_identifier.ResourceType.TASK,1824 _named_entity.NamedEntityIdentifier(project, domain, name),1825 _named_entity.NamedEntityMetadata(description, _named_entity.NamedEntityState.ACTIVE),1826 )1827 _click.echo("Successfully updated task")1828@_flyte_cli.command("update-launch-plan-meta", cls=_FlyteSubCommand)1829@_named_entity_description_option1830@_host_option1831@_insecure_option1832@_project_option1833@_domain_option1834@_optional_name_option1835def update_launch_plan_meta(description, host, insecure, project, domain, name):1836 """1837 Updates a launch plan entity under the scope specified by {project, domain, name} across versions.1838 """1839 _welcome_message()1840 client = _friendly_client.SynchronousFlyteClient(host, insecure=insecure)1841 client.update_named_entity(1842 _core_identifier.ResourceType.LAUNCH_PLAN,1843 _named_entity.NamedEntityIdentifier(project, domain, name),1844 _named_entity.NamedEntityMetadata(description, _named_entity.NamedEntityState.ACTIVE),1845 )1846 _click.echo("Successfully updated launch plan")1847@_flyte_cli.command("update-cluster-resource-attributes", cls=_FlyteSubCommand)1848@_host_option1849@_insecure_option1850@_project_option1851@_domain_option1852@_optional_name_option1853@_click.option("--attributes", type=(str, str), multiple=True)1854def update_cluster_resource_attributes(host, insecure, project, domain, name, attributes):1855 """1856 Sets matchable cluster resource attributes for a project, domain and optionally, workflow name.1857 The attribute names should match the templatized values you use to configure these resource1858 attributes in your flyteadmin deployment. See1859 https://lyft.github.io/flyte/administrator/install/managing_customizable_resources.html#cluster-resources1860 for more documentation.1861 e.g.1862 $ flyte-cli -h localhost:30081 -p flyteexamples -d development update-cluster-resource-attributes \1863 --attributes projectQuotaCpu 1 --attributes projectQuotaMemory 500M1864 """1865 _welcome_message()1866 client = _friendly_client.SynchronousFlyteClient(host, insecure=insecure)1867 cluster_resource_attributes = _ClusterResourceAttributes({attribute[0]: attribute[1] for attribute in attributes})1868 matching_attributes = _MatchingAttributes(cluster_resource_attributes=cluster_resource_attributes)1869 if name is not None:1870 client.update_workflow_attributes(project, domain, name, matching_attributes)1871 _click.echo(1872 "Successfully updated cluster resource attributes for project: {}, domain: {}, and workflow: {}".format(1873 project, domain, name1874 )1875 )1876 else:1877 client.update_project_domain_attributes(project, domain, matching_attributes)1878 _click.echo(1879 "Successfully updated cluster resource attributes for project: {} and domain: {}".format(project, domain)1880 )1881@_flyte_cli.command("update-execution-queue-attributes", cls=_FlyteSubCommand)1882@_host_option1883@_insecure_option1884@_project_option1885@_domain_option1886@_optional_name_option1887@_click.option("--tags", multiple=True, help="Tag(s) to be applied.")1888def update_execution_queue_attributes(host, insecure, project, domain, name, tags):1889 """1890 Tags used for assigning execution queues for tasks belonging to a project, domain and optionally, workflow name.1891 e.g.1892 $ flyte-cli -h localhost:30081 -p flyteexamples -d development update-execution-queue-attributes \1893 --tags critical --tags gpu_intensive1894 """1895 _welcome_message()1896 client = _friendly_client.SynchronousFlyteClient(host, insecure=insecure)1897 execution_queue_attributes = _ExecutionQueueAttributes(list(tags))1898 matching_attributes = _MatchingAttributes(execution_queue_attributes=execution_queue_attributes)1899 if name is not None:1900 client.update_workflow_attributes(project, domain, name, matching_attributes)1901 _click.echo(1902 "Successfully updated execution queue attributes for project: {}, domain: {}, and workflow: {}".format(1903 project, domain, name1904 )1905 )1906 else:1907 client.update_project_domain_attributes(project, domain, matching_attributes)1908 _click.echo(1909 "Successfully updated execution queue attributes for project: {} and domain: {}".format(project, domain)1910 )1911@_flyte_cli.command("update-execution-cluster-label", cls=_FlyteSubCommand)1912@_host_option1913@_insecure_option1914@_project_option1915@_domain_option1916@_optional_name_option1917@_click.option("--value", help="Cluster label for which to schedule matching executions")1918def update_execution_cluster_label(host, insecure, project, domain, name, value):1919 """1920 Label value to determine where an execution's task will be run for tasks belonging to a project, domain and1921 optionally, workflow name.1922 e.g.1923 $ flyte-cli -h localhost:30081 -p flyteexamples -d development update-execution-cluster-label --value foo1924 """1925 _welcome_message()1926 client = _friendly_client.SynchronousFlyteClient(host, insecure=insecure)1927 execution_cluster_label = _ExecutionClusterLabel(value)1928 matching_attributes = _MatchingAttributes(execution_cluster_label=execution_cluster_label)1929 if name is not None:1930 client.update_workflow_attributes(project, domain, name, matching_attributes)1931 _click.echo(1932 "Successfully updated execution cluster label for project: {}, domain: {}, and workflow: {}".format(1933 project, domain, name1934 )1935 )1936 else:1937 client.update_project_domain_attributes(project, domain, matching_attributes)1938 _click.echo(1939 "Successfully updated execution cluster label for project: {} and domain: {}".format(project, domain)1940 )1941@_flyte_cli.command("update-plugin-override", cls=_FlyteSubCommand)1942@_host_option1943@_insecure_option1944@_project_option1945@_domain_option1946@_optional_name_option1947@_click.option("--task-type", help="Task type for which to apply plugin implementation overrides")1948@_click.option("--plugin-id", multiple=True, help="Plugin id(s) to be used in place of the default for the task type.")1949@_click.option(1950 "--missing-plugin-behavior", help="Behavior when no specified plugin_id has an associated handler.", default="FAIL"1951)1952def update_plugin_override(host, insecure, project, domain, name, task_type, plugin_id, missing_plugin_behavior):1953 """1954 Plugin ids designating non-default plugin handlers to be used for tasks of a certain type.1955 e.g.1956 $ flyte-cli -h localhost:30081 -p flyteexamples -d development update-plugin-override --task-type python \1957 --plugin-id my_cool_plugin --plugin-id my_fallback_plugin --missing-plugin-behavior FAIL1958 """1959 _welcome_message()1960 client = _friendly_client.SynchronousFlyteClient(host, insecure=insecure)1961 plugin_override = _PluginOverride(1962 task_type, list(plugin_id), _PluginOverride.string_to_enum(missing_plugin_behavior.upper())1963 )1964 matching_attributes = _MatchingAttributes(plugin_overrides=_PluginOverrides(overrides=[plugin_override]))1965 if name is not None:1966 client.update_workflow_attributes(project, domain, name, matching_attributes)1967 _click.echo(1968 "Successfully updated plugin override for project: {}, domain: {}, and workflow: {}".format(1969 project, domain, name1970 )1971 )1972 else:1973 client.update_project_domain_attributes(project, domain, matching_attributes)1974 _click.echo("Successfully updated plugin override for project: {} and domain: {}".format(project, domain))1975@_flyte_cli.command("get-matching-attributes", cls=_FlyteSubCommand)1976@_host_option1977@_insecure_option1978@_project_option1979@_domain_option1980@_optional_name_option1981@_click.option(1982 "--resource-type",1983 help="Resource type",1984 required=True,1985 type=_click.Choice(1986 [1987 "task_resource",1988 "cluster_resource",1989 "execution_queue",1990 "execution_cluster_label",1991 "quality_of_service_specification",1992 ]1993 ),1994)1995def get_matching_attributes(host, insecure, project, domain, name, resource_type):1996 """1997 Fetches the matchable resource of the given resource type for this project, domain and optionally workflow name1998 combination.1999 """2000 _welcome_message()2001 client = _friendly_client.SynchronousFlyteClient(host, insecure=insecure)2002 if name is not None:2003 attributes = client.get_workflow_attributes(2004 project, domain, name, _MatchableResource.string_to_enum(resource_type.upper())2005 )2006 _click.echo("{}".format(attributes))2007 else:2008 attributes = client.get_project_domain_attributes(2009 project, domain, _MatchableResource.string_to_enum(resource_type.upper())2010 )2011 _click.echo("{}".format(attributes))2012@_flyte_cli.command("list-matching-attributes", cls=_FlyteSubCommand)2013@_host_option2014@_insecure_option2015@_click.option(2016 "--resource-type",2017 help="Resource type",2018 required=True,2019 type=_click.Choice(2020 [2021 "task_resource",2022 "cluster_resource",2023 "execution_queue",2024 "execution_cluster_label",2025 "quality_of_service_specification",2026 ]2027 ),2028)2029def list_matching_attributes(host, insecure, resource_type):2030 """2031 Fetches all matchable resources of the given resource type.2032 """2033 _welcome_message()2034 client = _friendly_client.SynchronousFlyteClient(host, insecure=insecure)2035 attributes = client.list_matchable_attributes(_MatchableResource.string_to_enum(resource_type.upper()))2036 for configuration in attributes.configurations:2037 _click.secho(2038 "{:20} {:20} {:20} {:20}\n".format(2039 _tt(configuration.project),2040 _tt(configuration.domain),2041 _tt(configuration.workflow),2042 _tt(configuration.launch_plan),2043 ),2044 fg="blue",2045 nl=False,2046 )2047 _click.echo("{}".format(configuration.attributes))2048@_flyte_cli.command("setup-config", cls=_click.Command)2049@_host_option2050@_insecure_option2051def setup_config(host, insecure):2052 """2053 Set-up a default config file.2054 """2055 _welcome_message()2056 config_file = _get_config_file_path()2057 if _get_user_filepath_home() and _os.path.exists(config_file):2058 _click.secho("Config file already exists at {}".format(_tt(config_file)), fg="blue")2059 return2060 # Before creating check that the directory exists and create if not2061 config_dir = _os.path.join(_get_user_filepath_home(), _default_config_file_dir)2062 if not _os.path.isdir(config_dir):2063 _click.secho(2064 "Creating default Flyte configuration directory at {}".format(_tt(config_dir)),2065 fg="blue",2066 )2067 _os.mkdir(config_dir)2068 full_host = "http://{}".format(host) if insecure else "https://{}".format(host)2069 config_url = _urlparse.urljoin(full_host, "config/v1/flyte_client")2070 response = _requests.get(config_url)2071 data = response.json()2072 with open(config_file, "w+") as f:2073 f.write("[platform]")2074 f.write("\n")2075 f.write("url={}".format(host))2076 f.write("\n")2077 f.write("insecure={}".format(insecure))2078 f.write("\n\n")2079 f.write("[credentials]")2080 f.write("\n")2081 f.write("client_id={}".format(data["client_id"]))2082 f.write("\n")2083 f.write("redirect_uri={}".format(data["redirect_uri"]))2084 f.write("\n")2085 f.write("scopes={}".format(data["scopes"]))2086 f.write("\n")2087 f.write("authorization_metadata_key={}".format(data["authorization_metadata_key"]))2088 f.write("\n")2089 f.write("auth_mode=standard")2090 f.write("\n")2091 set_flyte_config_file(config_file_path=config_file)2092 _click.secho("Wrote default config file to {}".format(_tt(config_file)), fg="blue")2093if __name__ == "__main__":...
MainPage.py
Source:MainPage.py
...38 CONTINUE_BUTTON = (By.CSS_SELECTOR, ".btn-primary")39 TABLETS_BUTTON = (By.LINK_TEXT, "Tablets")40 SOFTWARE_BUTTON = (By.LINK_TEXT, "Software")41 def go_to_registration(self):42 self._click(self.FIND_MY_ACCOUNT)43 self._click(self.REGISTER_BUTTON)44 def click_currency_button(self):45 self._click(self.CURRENCY_BUTTON)46 def usd_button_click(self):47 self._click(self.USD_BUTTON)48 def gbp_button_click(self):49 self._click(self.GBP_BUTTON)50 def eur_button_click(self):51 self._click(self.EUR_BUTTON)52 def usd_icon_check(self):53 self._element(self.USD_ICON)54 def gpb_icon_check(self):55 self._element(self.GBP_ICON)56 def eur_icon_check(self):57 self._element(self.EUR_ICON)58 def my_account_button_click(self):59 self._click(self.FIND_MY_ACCOUNT)60 def register_button_check(self):61 self._element(self.REGISTER_BUTTON)62 def login_button_check(self):63 self._element(self.LOGIN_BUTTON)64 def phone_button_click(self):65 self._click(self.PHONE_BUTTON)66 def wish_list_button_click(self):67 self._click(self.WISH_LIST_BUTTON)68 def shopping_cart_button_click(self):69 self._click(self.SHOPPING_CART_BUTTON)70 def checkout_button_click(self):71 self._click(self.CHECKOUT_BUTTON)72 def field_search_check(self):73 self._element(self.SEARCH_FIELD)74 def search_button_click(self):75 self._click(self.SEARCH_BUTTON)76 def search_text_check(self):77 self._element(self.SEARCH_TEXT)78 def shopping_preview_button_click(self):79 self._click(self.SHOPPING_PREVIEW_BUTTON)80 def empty_shopping_cart_text_check(self):81 self._element(self.EMPTY_SHOPPING_CART_TEXT)82 def upper_swiper_button_click(self):83 with allure.step(f"ÐÑÑ Ð¸ ÐºÐ»Ð¸ÐºÐ°Ñ Ð² ÑÐ»ÐµÐ¼ÐµÐ½Ñ {self.UPPER_SWIPER_BUTTON_FORWARD}"):84 try:85 self.logger.info(f"Click on an element {self.UPPER_SWIPER_BUTTON_FORWARD}")86 self.browser.find_element(*self.UPPER_SWIPER_BUTTON_FORWARD).click()87 except TimeoutException:88 self.add_screenshot_to_allure(self.UPPER_SWIPER_BUTTON_FORWARD)89 raise AssertionError(90 f"Unable to find or click on element: {self.UPPER_SWIPER_BUTTON_FORWARD} "91 f"on page {self.browser.current_url}")92 def upper_swiper_button_back_click(self):93 with allure.step(f"ÐÑÑ Ð¸ ÐºÐ»Ð¸ÐºÐ°Ñ Ð² ÑÐ»ÐµÐ¼ÐµÐ½Ñ {self.UPPER_SWIPER_BUTTON_BACK}"):94 try:95 self.logger.info(f"Click on an element {self.UPPER_SWIPER_BUTTON_BACK}")96 self.browser.find_element(*self.UPPER_SWIPER_BUTTON_BACK).click()97 except TimeoutException:98 self.add_screenshot_to_allure(self.UPPER_SWIPER_BUTTON_BACK)99 raise AssertionError(100 f"Unable to find or click on element: {self.UPPER_SWIPER_BUTTON_BACK} "101 f"on page {self.browser.current_url}")102 def product_item_click(self):103 self._elements(self.PRODUCT_ITEM)[random.randint(0, 3)].click()104 def add_to_cart_product(self):105 self._elements(self.ADD_TO_CART_BUTTON)[random.randint(2, 3)].click()106 # инаÑе ÑеÑÑ Ð¿Ð°Ð´Ð°ÐµÑ107 time.sleep(0.5)108 def remove_product(self):109 self._click(self.SHOPPING_PREVIEW_BUTTON)110 self._click(self.DELETE_BUTTON)111 def open_section_desktops(self):112 self._click(self.DESKTOPS_BUTTON)113 def go_to_show_all_desktops(self):114 self._click(self.SHOW_ALL_DESKTOPS_BUTTON)115 def go_to_pc_section(self):116 self._click(self.PC_BUTTON)117 def go_to_mac_section(self):118 self._click(self.MAC_BUTTON)119 def go_to_tablets_section(self):120 self._click(self.TABLETS_BUTTON)121 def go_to_software_section(self):122 self._click(self.SOFTWARE_BUTTON)123 def go_to_product(self):...
pose_demo.py
Source:pose_demo.py
1#!/usr/bin/env python2"""3Pose predictions in Python.45Caffe must be available on the Pythonpath for this to work. The methods can6be imported and used directly, or the command line interface can be used. In7the latter case, adjust the log-level to your needs. The maximum image size8for one prediction can be adjusted with the variable _MAX_SIZE so that it9still fits in GPU memory, all larger images are split in sufficiently small10parts.1112Authors: Christoph Lassner, based on the MATLAB implementation by Eldar13 Insafutdinov.14"""15# pylint: disable=invalid-name16import os as _os17import logging as _logging18import glob as _glob19import numpy as _np20import scipy as _scipy21import click as _click22import caffe as _caffe2324from estimate_pose import estimate_pose2526_LOGGER = _logging.getLogger(__name__)272829def _npcircle(image, cx, cy, radius, color, transparency=0.0):30 """Draw a circle on an image using only numpy methods."""31 radius = int(radius)32 cx = int(cx)33 cy = int(cy)34 y, x = _np.ogrid[-radius: radius, -radius: radius]35 index = x**2 + y**2 <= radius**236 image[cy-radius:cy+radius, cx-radius:cx+radius][index] = (37 image[cy-radius:cy+radius, cx-radius:cx+radius][index].astype('float32') * transparency +38 _np.array(color).astype('float32') * (1.0 - transparency)).astype('uint8')394041###############################################################################42# Command line interface.43###############################################################################4445@_click.command()46@_click.argument('image_name',47 type=_click.Path(exists=True, dir_okay=True, readable=True))48@_click.option('--out_name',49 type=_click.Path(dir_okay=True, writable=True),50 help='The result location to use. By default, use `image_name`_pose.npz.',51 default=None)52@_click.option('--scales',53 type=_click.STRING,54 help=('The scales to use, comma-separated. The most confident '55 'will be stored. Default: 1.'),56 default='1.')57@_click.option('--visualize',58 type=_click.BOOL,59 help='Whether to create a visualization of the pose. Default: True.',60 default=True)61@_click.option('--folder_image_suffix',62 type=_click.STRING,63 help=('The ending to use for the images to read, if a folder is '64 'specified. Default: .png.'),65 default='.png')66@_click.option('--use_cpu',67 type=_click.BOOL,68 is_flag=True,69 help='Use CPU instead of GPU for predictions.',70 default=False)71@_click.option('--gpu',72 type=_click.INT,73 help='GPU device id.',74 default=0)75def predict_pose_from(image_name,76 out_name=None,77 scales='1.',78 visualize=True,79 folder_image_suffix='.png',80 use_cpu=False,81 gpu=0):82 """83 Load an image file, predict the pose and write it out.84 85 `IMAGE_NAME` may be an image or a directory, for which all images with86 `folder_image_suffix` will be processed.87 """88 model_def = '../../models/deepercut/ResNet-152.prototxt'89 model_bin = '../../models/deepercut/ResNet-152.caffemodel'90 scales = [float(val) for val in scales.split(',')]91 if _os.path.isdir(image_name):92 folder_name = image_name[:]93 _LOGGER.info("Specified image name is a folder. Processing all images "94 "with suffix %s.", folder_image_suffix)95 images = _glob.glob(_os.path.join(folder_name, '*' + folder_image_suffix))96 process_folder = True97 else:98 images = [image_name]99 process_folder = False100 if use_cpu:101 _caffe.set_mode_cpu()102 else:103 _caffe.set_mode_gpu()104 _caffe.set_device(gpu)105 out_name_provided = out_name106 if process_folder and out_name is not None and not _os.path.exists(out_name):107 _os.mkdir(out_name)108 for image_name in images:109 if out_name_provided is None:110 out_name = image_name + '_pose.npz'111 elif process_folder:112 out_name = _os.path.join(out_name_provided,113 _os.path.basename(image_name) + '_pose.npz')114 _LOGGER.info("Predicting the pose on `%s` (saving to `%s`) in best of "115 "scales %s.", image_name, out_name, scales)116 image = _scipy.misc.imread(image_name)117 if image.ndim == 2:118 _LOGGER.warn("The image is grayscale! This may deteriorate performance!")119 image = _np.dstack((image, image, image))120 else:121 image = image[:, :, ::-1] 122 pose = estimate_pose(image, model_def, model_bin, scales)123 _np.savez_compressed(out_name, pose=pose)124 if visualize:125 visim = image[:, :, ::-1].copy()126 colors = [[255, 0, 0],[0, 255, 0],[0, 0, 255],[0,245,255],[255,131,250],[255,255,0],127 [255, 0, 0],[0, 255, 0],[0, 0, 255],[0,245,255],[255,131,250],[255,255,0],128 [0,0,0],[255,255,255]]129 for p_idx in range(14):130 _npcircle(visim,131 pose[0, p_idx],132 pose[1, p_idx],133 8,134 colors[p_idx],135 0.0)136 vis_name = out_name + '_vis.png'137 _scipy.misc.imsave(vis_name, visim)138139140if __name__ == '__main__':141 _logging.basicConfig(level=_logging.INFO)142 # pylint: disable=no-value-for-parameter
...
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!