1# -------------------------------------------------------------------------------------------- 2# Copyright (c) Microsoft Corporation. All rights reserved. 3# Licensed under the MIT License. See License.txt in the project root for license information. 4# -------------------------------------------------------------------------------------------- 5 6from msrest.exceptions import ValidationError 7from knack.log import get_logger 8from knack.util import CLIError 9from azure.cli.core.commands import LongRunningOperation 10 11from ._utils import ( 12 get_registry_by_name, 13 validate_managed_registry, 14 get_validate_platform, 15 get_custom_registry_credentials, 16 get_yaml_and_values 17) 18from ._stream_utils import stream_logs 19 20logger = get_logger(__name__) 21 22 23TASK_NOT_SUPPORTED = 'Task is only supported for managed registries.' 24DEFAULT_TOKEN_TYPE = 'PAT' 25NULL_CONTEXT = '/dev/null' 26IDENTITY_LOCAL_ID = '[system]' 27IDENTITY_GLOBAL_REMOVE = '[all]' 28 29DEFAULT_TIMEOUT_IN_SEC = 60 * 60 # 60 minutes 30DEFAULT_CPU = 2 31ALLOWED_TASK_FILE_TYPES = ('.yaml', '.yml', '.toml', '.json', '.sh', '.bash', '.zsh', '.ps1', 32 '.ps', '.cmd', '.bat', '.ts', '.js', '.php', '.py', '.rb', '.lua') 33 34 35def acr_task_create(cmd, # pylint: disable=too-many-locals 36 client, 37 task_name, 38 registry_name, 39 context_path, 40 file=None, 41 cmd_value=None, 42 git_access_token=None, 43 image_names=None, 44 status='Enabled', 45 platform=None, 46 cpu=DEFAULT_CPU, 47 timeout=DEFAULT_TIMEOUT_IN_SEC, 48 values=None, 49 source_trigger_name='defaultSourceTriggerName', 50 commit_trigger_enabled=True, 51 pull_request_trigger_enabled=True, 52 branch='master', 53 no_push=False, 54 no_cache=False, 55 arg=None, 56 secret_arg=None, 57 set_value=None, 58 set_secret=None, 59 base_image_trigger_name='defaultBaseimageTriggerName', 60 base_image_trigger_enabled=True, 61 base_image_trigger_type='Runtime', 62 resource_group_name=None, 63 assign_identity=None, 64 target=None, 65 auth_mode=None): 66 67 registry, resource_group_name = get_registry_by_name( 68 cmd.cli_ctx, registry_name, resource_group_name) 69 70 if context_path.lower() == NULL_CONTEXT: 71 context_path = None 72 commit_trigger_enabled = False 73 pull_request_trigger_enabled = False 74 75 if (commit_trigger_enabled or pull_request_trigger_enabled) and not git_access_token: 76 raise CLIError("If source control trigger is enabled [--commit-trigger-enabled] or " 77 "[--pull-request-trigger-enabled] --git-access-token must be provided.") 78 79 if cmd_value and file: 80 raise CLIError( 81 "Task can be created with either " 82 "--cmd myCommand -c /dev/null or " 83 "-f myFile -c myContext, but not both.") 84 85 if context_path: 86 if file.endswith(ALLOWED_TASK_FILE_TYPES): 87 FileTaskStep = cmd.get_models('FileTaskStep') 88 step = FileTaskStep( 89 task_file_path=file, 90 values_file_path=values, 91 context_path=context_path, 92 context_access_token=git_access_token, 93 values=(set_value if set_value else []) + (set_secret if set_secret else []) 94 ) 95 else: 96 DockerBuildStep = cmd.get_models('DockerBuildStep') 97 step = DockerBuildStep( 98 image_names=image_names, 99 is_push_enabled=not no_push, 100 no_cache=no_cache, 101 docker_file_path=file, 102 arguments=(arg if arg else []) + (secret_arg if secret_arg else []), 103 context_path=context_path, 104 context_access_token=git_access_token, 105 target=target 106 ) 107 else: 108 yaml_template, values_content = get_yaml_and_values( 109 cmd_value, timeout, file) 110 import base64 111 EncodedTaskStep = cmd.get_models('EncodedTaskStep') 112 step = EncodedTaskStep( 113 encoded_task_content=base64.b64encode( 114 yaml_template.encode()).decode(), 115 encoded_values_content=base64.b64encode( 116 values_content.encode()).decode(), 117 context_path=context_path, 118 context_access_token=git_access_token, 119 values=(set_value if set_value else []) + (set_secret if set_secret else []) 120 ) 121 122 SourceControlType, SourceTriggerEvent = cmd.get_models( 123 'SourceControlType', 'SourceTriggerEvent') 124 source_control_type = SourceControlType.visual_studio_team_service.value 125 if context_path is not None and 'GITHUB.COM' in context_path.upper(): 126 source_control_type = SourceControlType.github.value 127 128 source_triggers = None 129 source_trigger_events = [] 130 if commit_trigger_enabled: 131 source_trigger_events.append(SourceTriggerEvent.commit.value) 132 if pull_request_trigger_enabled: 133 source_trigger_events.append(SourceTriggerEvent.pullrequest.value) 134 # if source_trigger_events contains any event types we assume they are enabled 135 if source_trigger_events: 136 SourceTrigger, SourceProperties, AuthInfo, TriggerStatus = cmd.get_models( 137 'SourceTrigger', 'SourceProperties', 'AuthInfo', 'TriggerStatus') 138 source_triggers = [ 139 SourceTrigger( 140 source_repository=SourceProperties( 141 source_control_type=source_control_type, 142 repository_url=context_path, 143 branch=branch, 144 source_control_auth_properties=AuthInfo( 145 token=git_access_token, 146 token_type=DEFAULT_TOKEN_TYPE, 147 scope='repo' 148 ) 149 ), 150 source_trigger_events=source_trigger_events, 151 status=TriggerStatus.enabled.value, 152 name=source_trigger_name 153 ) 154 ] 155 156 base_image_trigger = None 157 if base_image_trigger_enabled: 158 BaseImageTrigger, TriggerStatus = cmd.get_models( 159 'BaseImageTrigger', 'TriggerStatus') 160 base_image_trigger = BaseImageTrigger( 161 base_image_trigger_type=base_image_trigger_type, 162 status=TriggerStatus.enabled.value if base_image_trigger_enabled else TriggerStatus.disabled.value, 163 name=base_image_trigger_name 164 ) 165 166 platform_os, platform_arch, platform_variant = get_validate_platform(cmd, platform) 167 168 Task, PlatformProperties, AgentProperties, TriggerProperties = cmd.get_models( 169 'Task', 'PlatformProperties', 'AgentProperties', 'TriggerProperties') 170 171 identity = None 172 if assign_identity is not None: 173 identity = _build_identities_info(cmd, assign_identity) 174 175 task_create_parameters = Task( 176 identity=identity, 177 location=registry.location, 178 step=step, 179 platform=PlatformProperties( 180 os=platform_os, 181 architecture=platform_arch, 182 variant=platform_variant 183 ), 184 status=status, 185 timeout=timeout, 186 agent_configuration=AgentProperties( 187 cpu=cpu 188 ), 189 trigger=TriggerProperties( 190 source_triggers=source_triggers, 191 base_image_trigger=base_image_trigger 192 ), 193 credentials=get_custom_registry_credentials( 194 cmd=cmd, 195 auth_mode=auth_mode 196 ) 197 ) 198 199 try: 200 return client.create(resource_group_name=resource_group_name, 201 registry_name=registry_name, 202 task_name=task_name, 203 task_create_parameters=task_create_parameters) 204 except ValidationError as e: 205 raise CLIError(e) 206 207 208def acr_task_show(cmd, 209 client, 210 task_name, 211 registry_name, 212 with_secure_properties=False, 213 resource_group_name=None): 214 _, resource_group_name = validate_managed_registry( 215 cmd, registry_name, resource_group_name, TASK_NOT_SUPPORTED) 216 217 if with_secure_properties: 218 return client.get_details(resource_group_name, registry_name, task_name) 219 return client.get(resource_group_name, registry_name, task_name) 220 221 222def acr_task_list(cmd, 223 client, 224 registry_name, 225 resource_group_name=None): 226 _, resource_group_name = validate_managed_registry( 227 cmd, registry_name, resource_group_name, TASK_NOT_SUPPORTED) 228 return client.list(resource_group_name, registry_name) 229 230 231def acr_task_delete(cmd, 232 client, 233 task_name, 234 registry_name, 235 resource_group_name=None): 236 _, resource_group_name = validate_managed_registry( 237 cmd, registry_name, resource_group_name, TASK_NOT_SUPPORTED) 238 return client.delete(resource_group_name, registry_name, task_name) 239 240 241def acr_task_update(cmd, # pylint: disable=too-many-locals 242 client, 243 task_name, 244 registry_name, 245 resource_group_name=None, 246 # task parameters 247 status=None, 248 platform=None, 249 cpu=None, 250 timeout=None, 251 context_path=None, 252 commit_trigger_enabled=None, 253 pull_request_trigger_enabled=None, 254 git_access_token=None, 255 branch=None, 256 image_names=None, 257 no_push=None, 258 no_cache=None, 259 file=None, 260 values=None, 261 arg=None, 262 secret_arg=None, 263 set_value=None, 264 set_secret=None, 265 base_image_trigger_enabled=None, 266 base_image_trigger_type=None, 267 target=None, 268 auth_mode=None): 269 _, resource_group_name = validate_managed_registry( 270 cmd, registry_name, resource_group_name, TASK_NOT_SUPPORTED) 271 272 task = client.get(resource_group_name, registry_name, task_name) 273 step = task.step 274 275 arguments = _get_all_override_arguments(arg, secret_arg) 276 set_values = _get_all_override_arguments(set_value, set_secret) 277 278 FileTaskStepUpdateParameters, DockerBuildStepUpdateParameters = cmd.get_models( 279 'FileTaskStepUpdateParameters', 'DockerBuildStepUpdateParameters') 280 if file and file.endswith(ALLOWED_TASK_FILE_TYPES): 281 step = FileTaskStepUpdateParameters( 282 task_file_path=file, 283 values_file_path=values, 284 context_path=context_path, 285 context_access_token=git_access_token, 286 values=set_values 287 ) 288 elif file and not file.endswith(ALLOWED_TASK_FILE_TYPES): 289 step = DockerBuildStepUpdateParameters( 290 image_names=image_names, 291 is_push_enabled=not no_push, 292 no_cache=no_cache, 293 docker_file_path=file, 294 arguments=arguments, 295 context_path=context_path, 296 context_access_token=git_access_token, 297 target=target 298 ) 299 elif step: 300 DockerBuildStep, FileTaskStep = cmd.get_models( 301 'DockerBuildStep', 'FileTaskStep') 302 if isinstance(step, DockerBuildStep): 303 step = DockerBuildStepUpdateParameters( 304 image_names=image_names, 305 is_push_enabled=not no_push, 306 no_cache=no_cache, 307 docker_file_path=file, 308 arguments=arguments, 309 context_path=context_path, 310 context_access_token=git_access_token, 311 target=target 312 ) 313 314 elif isinstance(step, FileTaskStep): 315 step = FileTaskStepUpdateParameters( 316 task_file_path=file, 317 values_file_path=values, 318 context_path=context_path, 319 context_access_token=git_access_token, 320 values=set_values 321 ) 322 323 source_control_type = None 324 if context_path: 325 SourceControlType = cmd.get_models('SourceControlType') 326 if 'GITHUB.COM' in context_path.upper(): 327 source_control_type = SourceControlType.github.value 328 else: 329 source_control_type = SourceControlType.visual_studio_team_service.value 330 331 # update trigger 332 source_trigger_update_params, base_image_trigger_update_params = None, None 333 if task.trigger: 334 TriggerStatus = cmd.get_models('TriggerStatus') 335 336 source_triggers = task.trigger.source_triggers 337 base_image_trigger = task.trigger.base_image_trigger 338 if (commit_trigger_enabled or pull_request_trigger_enabled) or source_triggers: 339 SourceTriggerUpdateParameters, SourceUpdateParameters, AuthInfoUpdateParameters = cmd.get_models( 340 'SourceTriggerUpdateParameters', 'SourceUpdateParameters', 'AuthInfoUpdateParameters') 341 342 source_trigger_events = _get_trigger_event_list(cmd, 343 source_triggers, 344 commit_trigger_enabled, 345 pull_request_trigger_enabled) 346 source_trigger_update_params = [ 347 SourceTriggerUpdateParameters( 348 source_repository=SourceUpdateParameters( 349 source_control_type=source_control_type, 350 repository_url=context_path, 351 branch=branch, 352 source_control_auth_properties=AuthInfoUpdateParameters( 353 token=git_access_token, 354 token_type=DEFAULT_TOKEN_TYPE 355 ) 356 ), 357 source_trigger_events=source_trigger_events, 358 status=TriggerStatus.enabled.value if source_trigger_events else TriggerStatus.disabled.value, 359 name=source_triggers[0].name if source_triggers else "defaultSourceTriggerName" 360 ) 361 ] 362 363 if base_image_trigger_enabled or base_image_trigger is not None: 364 BaseImageTriggerUpdateParameters = cmd.get_models( 365 'BaseImageTriggerUpdateParameters') 366 367 status = None 368 if base_image_trigger_enabled is not None: 369 status = TriggerStatus.enabled.value if base_image_trigger_enabled else TriggerStatus.disabled.value 370 base_image_trigger_update_params = BaseImageTriggerUpdateParameters( 371 base_image_trigger_type=base_image_trigger_type, 372 status=status, 373 name=base_image_trigger.name if base_image_trigger else "defaultBaseimageTriggerName" 374 ) 375 376 platform_os, platform_arch, platform_variant = None, None, None 377 if platform: 378 platform_os, platform_arch, platform_variant = get_validate_platform(cmd, platform) 379 380 TaskUpdateParameters, PlatformUpdateParameters, AgentProperties, TriggerUpdateParameters = cmd.get_models( 381 'TaskUpdateParameters', 'PlatformUpdateParameters', 'AgentProperties', 'TriggerUpdateParameters') 382 taskUpdateParameters = TaskUpdateParameters( 383 status=status, 384 platform=PlatformUpdateParameters( 385 os=platform_os, 386 architecture=platform_arch, 387 variant=platform_variant 388 ), 389 agent_configuration=AgentProperties( 390 cpu=cpu 391 ), 392 timeout=timeout, 393 step=step, 394 trigger=TriggerUpdateParameters( 395 source_triggers=source_trigger_update_params, 396 base_image_trigger=base_image_trigger_update_params 397 ), 398 credentials=get_custom_registry_credentials( 399 cmd=cmd, 400 auth_mode=auth_mode 401 ) 402 ) 403 404 return client.update(resource_group_name, registry_name, task_name, taskUpdateParameters) 405 406 407def acr_task_identity_assign(cmd, 408 client, 409 task_name, 410 registry_name, 411 identities=None, 412 resource_group_name=None): 413 _, resource_group_name = validate_managed_registry( 414 cmd, registry_name, resource_group_name, TASK_NOT_SUPPORTED) 415 416 identity = _build_identities_info(cmd, identities) 417 418 TaskUpdateParameters = cmd.get_models('TaskUpdateParameters') 419 420 taskUpdateParameters = TaskUpdateParameters( 421 identity=identity 422 ) 423 424 return client.update(resource_group_name, registry_name, task_name, taskUpdateParameters) 425 426 427def acr_task_identity_remove(cmd, 428 client, 429 task_name, 430 registry_name, 431 identities=None, 432 resource_group_name=None): 433 _, resource_group_name = validate_managed_registry( 434 cmd, registry_name, resource_group_name, TASK_NOT_SUPPORTED) 435 436 if identities and IDENTITY_GLOBAL_REMOVE in identities: 437 if len(identities) > 1: 438 raise CLIError( 439 "Cannot specify additional identities when [all] is used in [--identities]") 440 441 identity = None 442 if not identities or IDENTITY_LOCAL_ID in identities: 443 # To remove only the system assigned identity if user-assigned identities also exist 444 # PATCH with the existing user-assigned identities 445 # If no user-assigned identities exist, set the type to None 446 existingIdentity = client.get_details( 447 resource_group_name, registry_name, task_name).identity 448 identities = IDENTITY_GLOBAL_REMOVE if not existingIdentity else list( 449 existingIdentity.user_assigned_identities.keys()) 450 identity = _build_identities_info(cmd, identities) 451 else: 452 identity = _build_identities_info(cmd, identities, True) 453 454 TaskUpdateParameters = cmd.get_models('TaskUpdateParameters') 455 taskUpdateParameters = TaskUpdateParameters( 456 identity=identity 457 ) 458 459 return client.update(resource_group_name, registry_name, task_name, taskUpdateParameters) 460 461 462def acr_task_identity_show(cmd, 463 client, 464 task_name, 465 registry_name, 466 resource_group_name=None): 467 _, resource_group_name = validate_managed_registry( 468 cmd, registry_name, resource_group_name, TASK_NOT_SUPPORTED) 469 470 identity = client.get_details(resource_group_name, registry_name, task_name).identity 471 472 return {} if not identity else identity 473 474 475def acr_task_credential_add(cmd, 476 client, 477 task_name, 478 registry_name, 479 login_server, 480 username=None, 481 password=None, 482 use_identity=None, 483 resource_group_name=None): 484 _, resource_group_name = validate_managed_registry( 485 cmd, registry_name, resource_group_name, TASK_NOT_SUPPORTED) 486 487 existingCreds = client.get_details(resource_group_name, registry_name, task_name).credentials 488 existingCreds = {} if not existingCreds else existingCreds.custom_registries 489 490 if login_server in existingCreds: 491 raise CLIError("Login server '{}' already exists. You cannot add it again.".format(login_server)) 492 493 TaskUpdateParameters = cmd.get_models('TaskUpdateParameters') 494 taskUpdateParameters = TaskUpdateParameters( 495 credentials=get_custom_registry_credentials( 496 cmd=cmd, 497 login_server=login_server, 498 username=username, 499 password=password, 500 identity=use_identity 501 ) 502 ) 503 504 resp = LongRunningOperation(cmd.cli_ctx)( 505 client.update(resource_group_name, registry_name, task_name, taskUpdateParameters) 506 ) 507 resp = resp.credentials 508 return {} if not resp else resp.custom_registries 509 510 511def acr_task_credential_update(cmd, 512 client, 513 task_name, 514 registry_name, 515 login_server, 516 username=None, 517 password=None, 518 use_identity=None, 519 resource_group_name=None): 520 _, resource_group_name = validate_managed_registry( 521 cmd, registry_name, resource_group_name, TASK_NOT_SUPPORTED) 522 523 existingCreds = client.get_details(resource_group_name, registry_name, task_name).credentials 524 existingCreds = {} if not existingCreds else existingCreds.custom_registries 525 526 if login_server not in existingCreds: 527 raise CLIError("Login server '{}' not found.".format(login_server)) 528 529 TaskUpdateParameters = cmd.get_models('TaskUpdateParameters') 530 taskUpdateParameters = TaskUpdateParameters( 531 credentials=get_custom_registry_credentials( 532 cmd=cmd, 533 login_server=login_server, 534 username=username, 535 password=password, 536 identity=use_identity 537 ) 538 ) 539 540 resp = LongRunningOperation(cmd.cli_ctx)( 541 client.update(resource_group_name, registry_name, task_name, taskUpdateParameters) 542 ) 543 resp = resp.credentials 544 return {} if not resp else resp.custom_registries 545 546 547def acr_task_credential_remove(cmd, 548 client, 549 task_name, 550 registry_name, 551 login_server, 552 resource_group_name=None): 553 _, resource_group_name = validate_managed_registry( 554 cmd, registry_name, resource_group_name, TASK_NOT_SUPPORTED) 555 556 TaskUpdateParameters = cmd.get_models('TaskUpdateParameters') 557 taskUpdateParameters = TaskUpdateParameters( 558 credentials=get_custom_registry_credentials( 559 cmd=cmd, 560 login_server=login_server, 561 is_remove=True 562 ) 563 ) 564 565 resp = LongRunningOperation(cmd.cli_ctx)( 566 client.update(resource_group_name, registry_name, task_name, taskUpdateParameters) 567 ) 568 resp = resp.credentials 569 return {} if not resp else resp.custom_registries 570 571 572def acr_task_credential_list(cmd, 573 client, 574 task_name, 575 registry_name, 576 resource_group_name=None): 577 _, resource_group_name = validate_managed_registry( 578 cmd, registry_name, resource_group_name, TASK_NOT_SUPPORTED) 579 580 resp = client.get_details(resource_group_name, registry_name, task_name).credentials 581 return {} if not resp else resp.custom_registries 582 583 584def acr_task_update_run(cmd, 585 client, 586 run_id, 587 registry_name, 588 no_archive=None, 589 resource_group_name=None): 590 _, resource_group_name = validate_managed_registry( 591 cmd, registry_name, resource_group_name, TASK_NOT_SUPPORTED) 592 593 is_archive_enabled = not no_archive if no_archive is not None else None 594 595 return client.update(resource_group_name=resource_group_name, 596 registry_name=registry_name, 597 run_id=run_id, 598 is_archive_enabled=is_archive_enabled) 599 600 601def acr_task_run(cmd, 602 client, # cf_acr_runs 603 task_name, 604 registry_name, 605 set_value=None, 606 set_secret=None, 607 no_logs=False, 608 no_wait=False, 609 resource_group_name=None): 610 _, resource_group_name = validate_managed_registry( 611 cmd, registry_name, resource_group_name, TASK_NOT_SUPPORTED) 612 613 from ._client_factory import cf_acr_registries 614 client_registries = cf_acr_registries(cmd.cli_ctx) 615 TaskRunRequest = cmd.get_models('TaskRunRequest') 616 617 queued_run = LongRunningOperation(cmd.cli_ctx)( 618 client_registries.schedule_run( 619 resource_group_name, 620 registry_name, 621 TaskRunRequest( 622 task_name=task_name, 623 values=(set_value if set_value else []) + (set_secret if set_secret else []) 624 ) 625 ) 626 ) 627 628 run_id = queued_run.run_id 629 logger.warning("Queued a run with ID: %s", run_id) 630 631 if no_wait: 632 return queued_run 633 634 logger.warning("Waiting for an agent...") 635 636 if no_logs: 637 from ._run_polling import get_run_with_polling 638 return get_run_with_polling(cmd, client, run_id, registry_name, resource_group_name) 639 640 return stream_logs(client, run_id, registry_name, resource_group_name, True) 641 642 643def acr_task_show_run(cmd, 644 client, # cf_acr_runs 645 run_id, 646 registry_name, 647 resource_group_name=None): 648 _, resource_group_name = validate_managed_registry( 649 cmd, registry_name, resource_group_name, TASK_NOT_SUPPORTED) 650 return client.get(resource_group_name, registry_name, run_id) 651 652 653def acr_task_cancel_run(cmd, 654 client, # cf_acr_runs 655 run_id, 656 registry_name, 657 resource_group_name=None): 658 _, resource_group_name = validate_managed_registry( 659 cmd, registry_name, resource_group_name, TASK_NOT_SUPPORTED) 660 return client.cancel(resource_group_name, registry_name, run_id) 661 662 663def acr_task_list_runs(cmd, 664 client, # cf_acr_runs 665 registry_name, 666 top=15, 667 task_name=None, 668 run_status=None, 669 image=None, 670 resource_group_name=None): 671 _, resource_group_name = validate_managed_registry( 672 cmd, registry_name, resource_group_name, TASK_NOT_SUPPORTED) 673 674 filter_str = None 675 filter_str = _add_run_filter(filter_str, 'TaskName', task_name, 'eq') 676 filter_str = _add_run_filter(filter_str, 'Status', run_status, 'eq') 677 678 if image: 679 from .repository import get_image_digest 680 try: 681 repository, _, manifest = get_image_digest(cmd, registry_name, image) 682 filter_str = _add_run_filter( 683 filter_str, 'OutputImageManifests', '{}@{}'.format(repository, manifest), 'contains') 684 except CLIError as e: 685 raise CLIError("Could not find image '{}'. {}".format(image, e)) 686 687 return client.list(resource_group_name, registry_name, filter=filter_str, top=top) 688 689 690def _add_run_filter(orig_filter, name, value, operator): 691 if not value: 692 return orig_filter 693 694 if operator == 'contains': 695 new_filter_str = "contains({}, '{}')".format(name, value) 696 elif operator == 'eq': 697 new_filter_str = "{} eq '{}'".format(name, value) 698 else: 699 raise ValueError( 700 "Allowed filter operator: {}".format(['contains', 'eq'])) 701 702 return "{} and {}".format(orig_filter, new_filter_str) if orig_filter else new_filter_str 703 704 705def acr_task_logs(cmd, 706 client, # cf_acr_runs 707 registry_name, 708 run_id=None, 709 task_name=None, 710 image=None, 711 resource_group_name=None): 712 _, resource_group_name = validate_managed_registry( 713 cmd, registry_name, resource_group_name, TASK_NOT_SUPPORTED) 714 715 if not run_id: 716 # show logs for the last run 717 paged_runs = acr_task_list_runs(cmd, 718 client, 719 registry_name, 720 top=1, 721 task_name=task_name, 722 image=image) 723 try: 724 run_id = paged_runs.get(0)[0].run_id 725 logger.warning(_get_list_runs_message(base_message="Showing logs of the last created run", 726 task_name=task_name, 727 image=image)) 728 logger.warning("Run ID: %s", run_id) 729 except (AttributeError, KeyError, TypeError, IndexError): 730 raise CLIError(_get_list_runs_message(base_message="Could not find the last created run", 731 task_name=task_name, 732 image=image)) 733 734 return stream_logs(client, run_id, registry_name, resource_group_name) 735 736 737def _get_list_runs_message(base_message, task_name=None, image=None): 738 if task_name: 739 base_message = "{} for task '{}'".format(base_message, task_name) 740 if image: 741 base_message = "{} for image '{}'".format(base_message, image) 742 return "{}.".format(base_message) 743 744 745def _get_all_override_arguments(argument=None, secret_argument=None): 746 arguments = None 747 if argument is None and secret_argument is None: 748 arguments = None 749 else: 750 arguments = (argument if argument else []) + (secret_argument if secret_argument else []) 751 return arguments 752 753 754def _build_identities_info(cmd, identities, is_remove=False): 755 IdentityProperties, UserIdentityProperties, ResourceIdentityType = cmd.get_models( 756 'IdentityProperties', 'UserIdentityProperties', 'ResourceIdentityType') 757 identities = identities or [] 758 identity_types = [] 759 if IDENTITY_GLOBAL_REMOVE in identities: 760 return IdentityProperties(type=ResourceIdentityType.none.value) 761 if not identities or IDENTITY_LOCAL_ID in identities: 762 identity_types.append(ResourceIdentityType.system_assigned.value) 763 external_identities = [x for x in identities if x != IDENTITY_LOCAL_ID] 764 if external_identities: 765 identity_types.append(ResourceIdentityType.user_assigned.value) 766 identity_types = ', '.join(identity_types) 767 identity = IdentityProperties(type=identity_types) 768 if external_identities: 769 if is_remove: 770 identity.user_assigned_identities = {e: None for e in external_identities} 771 else: 772 identity.user_assigned_identities = {e: UserIdentityProperties() for e in external_identities} 773 return identity 774 775 776def _get_trigger_event_list(cmd, 777 source_triggers, 778 commit_trigger_enabled=None, 779 pull_request_trigger_enabled=None): 780 TriggerStatus, SourceTriggerEvent = cmd.get_models('TriggerStatus', 'SourceTriggerEvent') 781 782 source_trigger_events = set() 783 # perform merge with server-side event list 784 if source_triggers: 785 source_trigger_events = set(source_triggers[0].source_trigger_events) 786 if source_triggers[0].status == TriggerStatus.disabled.value: 787 source_trigger_events.clear() 788 if commit_trigger_enabled is not None: 789 if commit_trigger_enabled: 790 source_trigger_events.add(SourceTriggerEvent.commit.value) 791 else: 792 if SourceTriggerEvent.commit.value in source_trigger_events: 793 source_trigger_events.remove(SourceTriggerEvent.commit.value) 794 if pull_request_trigger_enabled is not None: 795 if pull_request_trigger_enabled: 796 source_trigger_events.add(SourceTriggerEvent.pullrequest.value) 797 else: 798 if SourceTriggerEvent.pullrequest.value in source_trigger_events: 799 source_trigger_events.remove(SourceTriggerEvent.pullrequest.value) 800 return source_trigger_events 801