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
6import base64
7from knack.log import get_logger
8from knack.util import CLIError
9from azure.cli.core.commands import LongRunningOperation
10
11from ._constants import ACR_CACHED_BUILDER_IMAGES
12from ._stream_utils import stream_logs
13from ._utils import (
14    get_registry_by_name,
15    get_validate_platform,
16    get_custom_registry_credentials
17)
18from ._client_factory import cf_acr_registries_tasks
19from .run import prepare_source_location
20
21PACK_TASK_YAML_FMT = '''version: v1.1.0
22steps:
23  - cmd: mcr.microsoft.com/oryx/pack:{pack_image_tag} build {image_name} --builder {builder} {no_pull} --env REGISTRY_NAME=$Registry -p .
24    timeout: 28800
25  - push: ["{image_name}"]
26    timeout: 1800
27'''
28
29logger = get_logger(__name__)
30
31
32def acr_pack_build(cmd,  # pylint: disable=too-many-locals
33                   client,
34                   registry_name,
35                   image_name,
36                   source_location,
37                   builder,
38                   pack_image_tag='stable',
39                   agent_pool_name=None,
40                   pull=False,
41                   no_format=False,
42                   no_logs=False,
43                   no_wait=False,
44                   timeout=None,
45                   resource_group_name=None,
46                   platform=None,
47                   auth_mode=None):
48    registry, resource_group_name = get_registry_by_name(cmd.cli_ctx, registry_name)
49
50    client_registries = cf_acr_registries_tasks(cmd.cli_ctx)
51    source_location = prepare_source_location(
52        cmd, source_location, client_registries, registry_name, resource_group_name)
53    if not source_location:
54        raise CLIError('Building with Buildpacks requires a valid source location.')
55
56    platform_os, platform_arch, platform_variant = get_validate_platform(cmd, platform)
57    OS = cmd.get_models('OS', operation_group='task_runs')
58    if platform_os != OS.linux.value.lower():
59        raise CLIError('Building with Buildpacks is only supported on Linux.')
60
61    if builder not in ACR_CACHED_BUILDER_IMAGES and not pull:
62        logger.warning('Using a non-cached builder image; `--pull` is probably needed as well')
63
64    registry_prefixes = '$Registry/', registry.login_server + '/'
65    # If the image name doesn't have any required prefix, add it
66    if all((not image_name.startswith(prefix) for prefix in registry_prefixes)):
67        original_image_name = image_name
68        image_name = registry_prefixes[0] + image_name
69        logger.debug('Modified image name from %s to %s', original_image_name, image_name)
70
71    yaml_body = PACK_TASK_YAML_FMT.format(
72        image_name=image_name,
73        builder=builder,
74        pack_image_tag=pack_image_tag,
75        no_pull='--no-pull' if not pull else '')
76
77    EncodedTaskRunRequest, PlatformProperties = cmd.get_models(
78        'EncodedTaskRunRequest',
79        'PlatformProperties',
80        operation_group='task_runs')
81
82    request = EncodedTaskRunRequest(
83        encoded_task_content=base64.b64encode(yaml_body.encode()).decode(),
84        source_location=source_location,
85        timeout=timeout,
86        platform=PlatformProperties(
87            os=platform_os,
88            architecture=platform_arch,
89            variant=platform_variant
90        ),
91        credentials=get_custom_registry_credentials(
92            cmd=cmd,
93            auth_mode=auth_mode
94        ),
95        agent_pool_name=agent_pool_name
96    )
97
98    queued = LongRunningOperation(cmd.cli_ctx)(client_registries.begin_schedule_run(
99        resource_group_name=resource_group_name,
100        registry_name=registry_name,
101        run_request=request))
102
103    run_id = queued.run_id
104    logger.warning('Queued a run with ID: %s', run_id)
105
106    if no_wait:
107        return queued
108
109    logger.warning('Waiting for an agent...')
110
111    if no_logs:
112        from ._run_polling import get_run_with_polling
113        return get_run_with_polling(cmd, client, run_id, registry_name, resource_group_name)
114
115    return stream_logs(cmd, client, run_id, registry_name, resource_group_name, timeout, no_format, True)
116