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