Skip to content

Commit 7f7f1fe

Browse files
StrawnSCcalvinsIDrunefaHaroon Feisalanthonychu
authored
4/26 release: Up with --repo/--browse, exec (ssh) command, replica commands, log streaming commands (Azure#72)
* Skeleton code * az containerapp env show * List kube/managed environments * Create kube environment, wait doesn't work yet * Update containerapp stubs (check if it is supported now) * Containerapp env delete, polling not working yet * Added polling for create and delete * Use Microsoft.App RP for show, list, delete command * Create containerapp env using Microsoft.App RP * Add optional containerapp env create arguments * Remove old kube environment code, naming fixes * Containerapp create almost done * Done containerapp create, except for --yaml. Need to test * Containerapp show, list * Fix helptext * Containerapp delete * Containerapp update. Needs secrets api to be implemented, and testing * Add scale command * Various validations, small fixes * listSecrets API for updates, autogen log analytics for env * Use space delimiter for secrets and env variables * Verify sub is registered to Microsoft.ContainerRegistration if creating vnet enabled env, remove logs-type parameter * Containerapp create --yaml * Fix updating registry to do create or update * Fix containerapp update command. Add image-name parameter to support multi container updates. Fix updating registries, containers and secrets * started update with --yaml. Need to do create or update for when an attribute is a list of items * use space delimiter for startup_command and args, instead of comma delimiter * Traffic weights * List and show revisions * az containerapp revision restart, activate, deactivate * Add ability for users to clear args/command in az containerapp update * Various fixes, traffic weights fixes * Verify subnet subscription is registered to Microsoft.ContainerServices * GitHub Actions Update (Azure#17) * Added models. Finished transferring Calvin's previous work. * Updated wrong models. * Updated models in custom.py, added githubactionclient. * Updated envelope to be correct. * Small bug fixes. * Updated error handling. Fixed bugs. Initial working state. * Added better error handling. * Added error messages for tokens with inappropriate access rights. * Added back get_acr_cred. * Fixed problems from merge conflict. * Updated names of imports from ._models.py to fix pylance erros. * Removed random imports. Co-authored-by: Haroon Feisal <haroonfeisal@microsoft.com> * Remove --location since location must be same as managed env * Add options for flag names: --env-vars and --registry-srever * Empty string to clear env_vars * Default revisions_mode to single * Infer acr credentials if it is acr and credentials are not provided * fix help msg * if image is hosted on acr, and no registry server is supplied, infer the registry server * Added subgroups (Ingress, Registry, Secret) and updated revisions (Azure#18) * Added ingress subgroup. * Added help for ingress. * Fixed ingress traffic help. * Added registry commands. * Updated registry remove util to clear secrets if none remaining. Added warning when updating existing registry. Added registry help. * Changed registry delete to remove. * Added error message if user tries to remove non assigned registry. * Changed registry add back to registry set. * Added secret subgroup commands. * Removed yaml support from secret set. * Changed secret add to secret set. Updated consistency between secret set and secret delete. Added secret help. Require at least one secret passed with --secrets for secret commands. * Changed param name for secret delete from --secrets to --secret-names. Updated help. * Changed registry remove to registry delete. * Fixed bug in registry delete. * Added revision mode set and revision copy. * Modified update_containerapp_yaml to support updating from non-current revision. Authored-by: Haroon Feisal <haroonfeisal@microsoft.com> * More p0 fixes (Azure#20) * Remove --registry-login-server, only allow --registry-server * Rename --environment-variables to --env-vars * If no image is supplied, use default quickstart image * Update help text (Azure#21) * Update help text * Update punctuation * master -> main * New 1.0.1 version * Added identity commands + --assign-identity flag to containerapp create (#8) * Added identity show and assign. * Finisheed identity remove. * Added helps, updated identity remove to work with identity names instead of requiring identity resource ids. * Moved helper function to utils. * Require --identities flag when removing identities. * Added message for assign identity with no specified identity. * Added --assign-identity flag to containerapp create. * Moved assign-identity flag to containerapp create. * Fixed small logic error on remove identities when passing duplicate identities. Added warnings for certain edge cases. * Updated param definition for identity assign --identity default. * Added identity examples in help. * Made sure secrets were not removed when assigning identities. Added tolerance for [system] passed with capital letters. * Fixed error from merge. Co-authored-by: Haroon Feisal <haroonfeisal@microsoft.com> * Dapr Commands (Azure#23) * Added ingress subgroup. * Added help for ingress. * Fixed ingress traffic help. * Added registry commands. * Updated registry remove util to clear secrets if none remaining. Added warning when updating existing registry. Added registry help. * Changed registry delete to remove. * Added error message if user tries to remove non assigned registry. * Changed registry add back to registry set. * Added secret subgroup commands. * Removed yaml support from secret set. * Changed secret add to secret set. Updated consistency between secret set and secret delete. Added secret help. Require at least one secret passed with --secrets for secret commands. * Changed param name for secret delete from --secrets to --secret-names. Updated help. * Changed registry remove to registry delete. * Fixed bug in registry delete. * Added revision mode set and revision copy. * Added dapr enable and dapr disable. Need to test more. * Added list, show, set dapr component. Added dapr enable, disable. * Added delete dapr delete. * Added helps and param text. * Changed dapr delete to dapr remove to match with dapr set. * Commented out managed identity for whl file. * Uncommented. Co-authored-by: Haroon Feisal <haroonfeisal@microsoft.com> * Rename --image-name to --container-name * Remove allowInsecure since it was messing with the api parsing * Fix for env var being empty string * Rename to --dapr-instrumentation-key, only infer ACR credentials if --registry-server is provided * Remove az containerapp scale * Fix delete containerapp errors * Remove ingress, dapr flags from az containerapp update/revision copy * Fix revision list -o table * Help text fix * Bump extension to 0.1.2 * Update managed identities and Dapr help text (Azure#25) * Update managed identities and Dapr help text * Update Dapr flags * Add secretref note * Env var options + various bug fixes (Azure#26) * Moved dapr arguments to env as a subgroup. * Added env variable options. * Changed revision mode set to revision set-mode. * Added env var options to revision copy. * Fixed revision copy bug related to env secret refs. * Changed registry and secret delete to remove. Added registry param helps. Removed replica from table output and added trafficWeight. * Updating warning text. * Updated warning text once more. * Made name optional for revision copy if from-revision flag is passed. Co-authored-by: Haroon Feisal <haroonfeisal@microsoft.com> * Fixed style issues, various bug fixes (Azure#27) * Moved dapr arguments to env as a subgroup. * Added env variable options. * Changed revision mode set to revision set-mode. * Added env var options to revision copy. * Fixed revision copy bug related to env secret refs. * Changed registry and secret delete to remove. Added registry param helps. Removed replica from table output and added trafficWeight. * Updating warning text. * Updated warning text once more. * Made name optional for revision copy if from-revision flag is passed. * Fixed whitespace style issues. * Styled clients and utils to pass pylint. * Finished client.py pylint fixes. * Fixed pylint issues. * Fixed flake8 commands and custom. * Fixed flake issues in src. * Added license header to _sdk_models. * Added confirmation for containerapp delete. Co-authored-by: Haroon Feisal <haroonfeisal@microsoft.com> * Update src/containerapp/azext_containerapp/tests/latest/test_containerapp_scenario.py Co-authored-by: Xing Zhou <Zhou.Xing@microsoft.com> * Specific Error Types + Bugfixes (Help, remove app-subnet-resource-id, removed env-var alias, added help text for --name) (Azure#28) * Moved dapr arguments to env as a subgroup. * Added env variable options. * Changed revision mode set to revision set-mode. * Added env var options to revision copy. * Fixed revision copy bug related to env secret refs. * Changed registry and secret delete to remove. Added registry param helps. Removed replica from table output and added trafficWeight. * Updating warning text. * Updated warning text once more. * Made name optional for revision copy if from-revision flag is passed. * Fixed whitespace style issues. * Styled clients and utils to pass pylint. * Finished client.py pylint fixes. * Fixed pylint issues. * Fixed flake8 commands and custom. * Fixed flake issues in src. * Added license header to _sdk_models. * Added confirmation for containerapp delete. * Update helps for identity, revision. Removed env-var alias for set-env-vars. Added name param help. * Removed app-subnet-resource-id. * Updated infrastructure subnet param help. * Check if containerapp resource exists before attempting to delete. * Added check before deleting managed env. * Changed error types to be more specific. * Removed check before deletion. Removed comments. Co-authored-by: Haroon Feisal <haroonfeisal@microsoft.com> * Reset to 0.1.0 version, remove unneeded options-list * Update min cli core version * Fixed style issues. (Azure#30) Co-authored-by: Haroon Feisal <haroonfeisal@microsoft.com> * Fix linter issues * Use custom-show-command * Removed --ids from revision, secret, registry list. * Add linter exclusions * Fix polling on delete containerapp * Fix error handling * Add Container App Service * Fix flake linter * Fix help text * Mark extension as preview * Add python 3.9 and 3.10 as supported * Remove registries and secrets from az containerapp update, in favor of registry and secret subgroup * Fix YAML not working * Move import to inside deserialize function * Dapr moved from Template to Configuration * Use aka.ms link for containerapps yaml * Updated dapr enable/disable to current spec. * Fixed oversight. * Remove revisions-mode from containerapp update * Fixed dapr enable property names. (Azure#47) Co-authored-by: Haroon Feisal <haroonfeisal@microsoft.com> * Fix exceptions with using --yaml in containerapp create/update * Rename history msg * Include fqdn in containerapp table output * Added ingress messages. * Revert history msg * Add basic test case * Remove managed-identity support for first release of CLI * Need to investigate test flakiness * Update _help.py removing duplicate help * Added prototype of container up. * Fixed deploy from acr registry image infer credentials issue. * Tried to add source. * Added acr build. * Finished acr build functionality. * Added acr create functionality and pull registry from existing containerapp if it exists. * Fixed bugs. * Check if rg exists and create one with name if it doesn't. * initial containerapp ssh implementation * fix interactive commands (vim); handle ctrl + c instead of exiting * fix style and linter issues * Added disable verbose. Moved utils into utils.py. * fix for ssh for windows clients * fix for unix * Disable verbose now uses sdk poller so it gives running animation. * Added helps for params. Added error handling for non acr registry passed with source. Ignore param disable_warnings for create and no_wait for up. * Updated disable_warnings ignore. Removed disable_warnings from update_containerapp. * add terminal resizing * reorganize code; implement terminal resizing, add startup command param, etc * organize code, remove token from warning output * add validations, add replica commands * use the correct API for fetching default container; remove is_preview * Renamed silent to quiet. * Fixed style issues. * add log streaming, bump version number and add to HISTORY.rst * add basic ssh test * Added workspace name and fqdn to dry_run_str. Added indicators of if the resources are new or existing to dry_run_str. * fix ssh test for windows * Check RP for location when not provided. Open Dockerfile and use EXPOSE for CA port. * fix windows arrow keys after exit * fix typo, add logstream test, remove token from logstream output * Removed print statement. * Updated dockerfile expose automatic ingress feature. * Removed dry run str, added dry run obj instead. * use bearer auth; fix --command bug * add handling for smooth transition to new URL path * Fixed merge conflict. * fix merge conflicts * Create env if name passed and it doesn't exist. * Added missing import from merge. * Added prototype for new environment workflow. * Finished environment logic. * Minor updates before demo. * add 'az containerapp github up' (wip) * various fixes for demo * rearrange github up code * merge haroonf/containerappup * start up refactor * add --repo to up and refactor up * reorganize code more; fix various bugs * fix linter issues, fix lingering exec/tail improvements * update history * update output * bug fixes for --repo * fix --source bug * fix --source * minor bug fixes * Added API change. * Finished API change, added helloworld image auto ingress, checked provisioning state beforehand. * fixes for sisira's comments * fix minor typo * bug fix where commands fail if providing registry creds * Fixed style issues. * Updated help and version text. Co-authored-by: Calvin Chan <calvinch4n@gmail.com> Co-authored-by: Haroon Feisal <38823870+haroonf@users.noreply.github.com> Co-authored-by: Haroon Feisal <haroonfeisal@microsoft.com> Co-authored-by: Anthony Chu <anthony@anthonychu.ca> Co-authored-by: Xing Zhou <Zhou.Xing@microsoft.com> Co-authored-by: Sisira Panchagnula <panchagnula@users.noreply.github.com>
1 parent 4e805bf commit 7f7f1fe

16 files changed

Lines changed: 2427 additions & 82 deletions

src/containerapp/HISTORY.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,13 @@
33
Release History
44
===============
55

6+
0.3.2
7+
++++++
8+
* Added 'az containerapp up' to create or update a container app and all associated resources (container app environment, ACR, Github Actions, resource group, etc.)
9+
* Open an ssh-like shell in a Container App with 'az containerapp exec'
10+
* Support for log streaming with 'az containerapp logs show'
11+
* Replica show and list commands
12+
613
0.3.1
714
++++++
815
* Update "az containerapp github-action add" parameters: replace --docker-file-path with --context-path, add --image.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
[flake8]
2+
ignore =
3+
W503 # line break before binary operator, not compliant with PEP 8
4+
E203 # whitespace before ':', not compliant with PEP 8
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
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+
# pylint: disable=line-too-long, consider-using-f-string
6+
7+
import time
8+
9+
from msrest import Deserializer
10+
from msrestazure.azure_exceptions import CloudError
11+
from azure.cli.core.profiles import ResourceType
12+
from azure.cli.command_modules.acr._constants import get_acr_task_models
13+
from azure.core.polling import PollingMethod, LROPoller
14+
15+
16+
def get_run_with_polling(cmd,
17+
client,
18+
run_id,
19+
registry_name,
20+
resource_group_name):
21+
deserializer = Deserializer(
22+
{k: v for k, v in get_acr_task_models(cmd).__dict__.items() if isinstance(v, type)})
23+
24+
def deserialize_run(response):
25+
return deserializer('Run', response)
26+
27+
return LROPoller(
28+
client=client,
29+
initial_response=client.get(
30+
resource_group_name, registry_name, run_id, cls=lambda x, y, z: x),
31+
deserialization_callback=deserialize_run,
32+
polling_method=RunPolling(
33+
cmd=cmd,
34+
registry_name=registry_name,
35+
run_id=run_id
36+
))
37+
38+
39+
class RunPolling(PollingMethod): # pylint: disable=too-many-instance-attributes
40+
41+
def __init__(self, cmd, registry_name, run_id, timeout=30):
42+
self._cmd = cmd
43+
self._registry_name = registry_name
44+
self._run_id = run_id
45+
self._timeout = timeout
46+
self._client = None
47+
self._response = None # Will hold latest received response
48+
self._url = None # The URL used to get the run
49+
self._deserialize = None # The deserializer for Run
50+
self.operation_status = ""
51+
self.operation_result = None
52+
53+
def initialize(self, client, initial_response, deserialization_callback):
54+
self._client = client._client # pylint: disable=protected-access
55+
self._response = initial_response
56+
self._url = initial_response.http_request.url
57+
self._deserialize = deserialization_callback
58+
59+
self._set_operation_status(initial_response)
60+
61+
def run(self):
62+
while not self.finished():
63+
time.sleep(self._timeout)
64+
self._update_status()
65+
66+
if self.operation_status not in get_succeeded_run_status(self._cmd):
67+
from knack.util import CLIError
68+
raise CLIError("The run with ID '{}' finished with unsuccessful status '{}'. "
69+
"Show run details by 'az acr task show-run -r {} --run-id {}'. "
70+
"Show run logs by 'az acr task logs -r {} --run-id {}'.".format(
71+
self._run_id,
72+
self.operation_status,
73+
self._registry_name,
74+
self._run_id,
75+
self._registry_name,
76+
self._run_id
77+
))
78+
79+
def status(self):
80+
return self.operation_status
81+
82+
def finished(self):
83+
return self.operation_status in get_finished_run_status(self._cmd)
84+
85+
def resource(self):
86+
return self.operation_result
87+
88+
def _set_operation_status(self, response):
89+
if response.http_response.status_code == 200:
90+
self.operation_result = self._deserialize(response)
91+
self.operation_status = self.operation_result.status
92+
return
93+
raise CloudError(response)
94+
95+
def _update_status(self):
96+
self._response = self._client._pipeline.run( # pylint: disable=protected-access
97+
self._client.get(self._url), stream=False)
98+
self._set_operation_status(self._response)
99+
100+
101+
def get_succeeded_run_status(cmd):
102+
RunStatus = cmd.get_models('RunStatus', resource_type=ResourceType.MGMT_CONTAINERREGISTRY, operation_group='task_runs')
103+
return [RunStatus.succeeded.value]
104+
105+
106+
def get_finished_run_status(cmd):
107+
RunStatus = cmd.get_models('RunStatus', resource_type=ResourceType.MGMT_CONTAINERREGISTRY, operation_group='task_runs')
108+
return [RunStatus.succeeded.value,
109+
RunStatus.failed.value,
110+
RunStatus.canceled.value,
111+
RunStatus.error.value,
112+
RunStatus.timeout.value]
Lines changed: 243 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,243 @@
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+
# pylint: disable=consider-using-f-string, consider-using-with, no-member
6+
7+
import tarfile
8+
import os
9+
import re
10+
import codecs
11+
from io import open
12+
import requests
13+
from knack.log import get_logger
14+
from msrestazure.azure_exceptions import CloudError
15+
from azure.cli.core.azclierror import (CLIInternalError)
16+
from azure.cli.core.profiles import ResourceType, get_sdk
17+
from azure.cli.command_modules.acr._azure_utils import get_blob_info
18+
from azure.cli.command_modules.acr._constants import TASK_VALID_VSTS_URLS
19+
20+
logger = get_logger(__name__)
21+
22+
23+
def upload_source_code(cmd, client,
24+
registry_name,
25+
resource_group_name,
26+
source_location,
27+
tar_file_path,
28+
docker_file_path,
29+
docker_file_in_tar):
30+
_pack_source_code(source_location,
31+
tar_file_path,
32+
docker_file_path,
33+
docker_file_in_tar)
34+
35+
size = os.path.getsize(tar_file_path)
36+
unit = 'GiB'
37+
for S in ['Bytes', 'KiB', 'MiB', 'GiB']:
38+
if size < 1024:
39+
unit = S
40+
break
41+
size = size / 1024.0
42+
43+
logger.info("Uploading archived source code from '%s'...", tar_file_path)
44+
upload_url = None
45+
relative_path = None
46+
try:
47+
source_upload_location = client.get_build_source_upload_url(
48+
resource_group_name, registry_name)
49+
upload_url = source_upload_location.upload_url
50+
relative_path = source_upload_location.relative_path
51+
except (AttributeError, CloudError) as e:
52+
raise CLIInternalError("Failed to get a SAS URL to upload context. Error: {}".format(e.message)) from e
53+
54+
if not upload_url:
55+
raise CLIInternalError("Failed to get a SAS URL to upload context.")
56+
57+
account_name, endpoint_suffix, container_name, blob_name, sas_token = get_blob_info(upload_url)
58+
BlockBlobService = get_sdk(cmd.cli_ctx, ResourceType.DATA_STORAGE, 'blob#BlockBlobService')
59+
BlockBlobService(account_name=account_name,
60+
sas_token=sas_token,
61+
endpoint_suffix=endpoint_suffix,
62+
# Increase socket timeout from default of 20s for clients with slow network connection.
63+
socket_timeout=300).create_blob_from_path(
64+
container_name=container_name,
65+
blob_name=blob_name,
66+
file_path=tar_file_path)
67+
logger.info("Sending context ({0:.3f} {1}) to registry: {2}...".format(
68+
size, unit, registry_name))
69+
return relative_path
70+
71+
72+
def _pack_source_code(source_location, tar_file_path, docker_file_path, docker_file_in_tar):
73+
logger.info("Packing source code into tar to upload...")
74+
75+
original_docker_file_name = os.path.basename(docker_file_path.replace("\\", os.sep))
76+
ignore_list, ignore_list_size = _load_dockerignore_file(source_location, original_docker_file_name)
77+
common_vcs_ignore_list = {'.git', '.gitignore', '.bzr', 'bzrignore', '.hg', '.hgignore', '.svn'}
78+
79+
def _ignore_check(tarinfo, parent_ignored, parent_matching_rule_index):
80+
# ignore common vcs dir or file
81+
if tarinfo.name in common_vcs_ignore_list:
82+
logger.info("Excluding '%s' based on default ignore rules", tarinfo.name)
83+
return True, parent_matching_rule_index
84+
85+
if ignore_list is None:
86+
# if .dockerignore doesn't exists, inherit from parent
87+
# eg, it will ignore the files under .git folder.
88+
return parent_ignored, parent_matching_rule_index
89+
90+
for index, item in enumerate(ignore_list):
91+
# stop checking the remaining rules whose priorities are lower than the parent matching rule
92+
# at this point, current item should just inherit from parent
93+
if index >= parent_matching_rule_index:
94+
break
95+
if re.match(item.pattern, tarinfo.name):
96+
logger.debug(".dockerignore: rule '%s' matches '%s'.",
97+
item.rule, tarinfo.name)
98+
return item.ignore, index
99+
100+
logger.debug(".dockerignore: no rule for '%s'. parent ignore '%s'",
101+
tarinfo.name, parent_ignored)
102+
# inherit from parent
103+
return parent_ignored, parent_matching_rule_index
104+
105+
with tarfile.open(tar_file_path, "w:gz") as tar:
106+
# need to set arcname to empty string as the archive root path
107+
_archive_file_recursively(tar,
108+
source_location,
109+
arcname="",
110+
parent_ignored=False,
111+
parent_matching_rule_index=ignore_list_size,
112+
ignore_check=_ignore_check)
113+
114+
# Add the Dockerfile if it's specified.
115+
# In the case of run, there will be no Dockerfile.
116+
if docker_file_path:
117+
docker_file_tarinfo = tar.gettarinfo(
118+
docker_file_path, docker_file_in_tar)
119+
with open(docker_file_path, "rb") as f:
120+
tar.addfile(docker_file_tarinfo, f)
121+
122+
123+
class IgnoreRule: # pylint: disable=too-few-public-methods
124+
def __init__(self, rule):
125+
126+
self.rule = rule
127+
self.ignore = True
128+
# ! makes exceptions to exclusions
129+
if rule.startswith('!'):
130+
self.ignore = False
131+
rule = rule[1:] # remove !
132+
# load path without leading slash in linux and windows
133+
# environments (interferes with dockerignore file)
134+
if rule.startswith('/'):
135+
rule = rule[1:] # remove beginning '/'
136+
137+
self.pattern = "^"
138+
tokens = rule.split('/')
139+
token_length = len(tokens)
140+
for index, token in enumerate(tokens, 1):
141+
# ** matches any number of directories
142+
if token == "**":
143+
self.pattern += ".*" # treat **/ as **
144+
else:
145+
# * matches any sequence of non-seperator characters
146+
# ? matches any single non-seperator character
147+
# . matches dot character
148+
self.pattern += token.replace(
149+
"*", "[^/]*").replace("?", "[^/]").replace(".", "\\.")
150+
if index < token_length:
151+
self.pattern += "/" # add back / if it's not the last
152+
self.pattern += "$"
153+
154+
155+
def _load_dockerignore_file(source_location, original_docker_file_name):
156+
# reference: https://docs.docker.com/engine/reference/builder/#dockerignore-file
157+
docker_ignore_file = os.path.join(source_location, ".dockerignore")
158+
docker_ignore_file_override = None
159+
if original_docker_file_name != "Dockerfile":
160+
docker_ignore_file_override = os.path.join(
161+
source_location, "{}.dockerignore".format(original_docker_file_name))
162+
if os.path.exists(docker_ignore_file_override):
163+
logger.info("Overriding .dockerignore with %s", docker_ignore_file_override)
164+
docker_ignore_file = docker_ignore_file_override
165+
166+
if not os.path.exists(docker_ignore_file):
167+
return None, 0
168+
169+
encoding = "utf-8"
170+
header = open(docker_ignore_file, "rb").read(len(codecs.BOM_UTF8))
171+
if header.startswith(codecs.BOM_UTF8):
172+
encoding = "utf-8-sig"
173+
174+
ignore_list = []
175+
if docker_ignore_file == docker_ignore_file_override:
176+
ignore_list.append(IgnoreRule(".dockerignore"))
177+
178+
for line in open(docker_ignore_file, 'r', encoding=encoding).readlines():
179+
rule = line.rstrip()
180+
181+
# skip empty line and comment
182+
if not rule or rule.startswith('#'):
183+
continue
184+
185+
# the ignore rule at the end has higher priority
186+
ignore_list = [IgnoreRule(rule)] + ignore_list
187+
188+
return ignore_list, len(ignore_list)
189+
190+
191+
def _archive_file_recursively(tar, name, arcname, parent_ignored, parent_matching_rule_index, ignore_check):
192+
# create a TarInfo object from the file
193+
tarinfo = tar.gettarinfo(name, arcname)
194+
195+
if tarinfo is None:
196+
raise CLIInternalError("tarfile: unsupported type {}".format(name))
197+
198+
# check if the file/dir is ignored
199+
ignored, matching_rule_index = ignore_check(
200+
tarinfo, parent_ignored, parent_matching_rule_index)
201+
202+
if not ignored:
203+
# append the tar header and data to the archive
204+
if tarinfo.isreg():
205+
with open(name, "rb") as f:
206+
tar.addfile(tarinfo, f)
207+
else:
208+
tar.addfile(tarinfo)
209+
210+
# even the dir is ignored, its child items can still be included, so continue to scan
211+
if tarinfo.isdir():
212+
for f in os.listdir(name):
213+
_archive_file_recursively(tar, os.path.join(name, f), os.path.join(arcname, f),
214+
parent_ignored=ignored, parent_matching_rule_index=matching_rule_index,
215+
ignore_check=ignore_check)
216+
217+
218+
def check_remote_source_code(source_location):
219+
lower_source_location = source_location.lower()
220+
221+
# git
222+
if lower_source_location.startswith("git@") or lower_source_location.startswith("git://"):
223+
return source_location
224+
225+
# http
226+
if lower_source_location.startswith("https://") or lower_source_location.startswith("http://") \
227+
or lower_source_location.startswith("github.com/"):
228+
isVSTS = any(url in lower_source_location for url in TASK_VALID_VSTS_URLS)
229+
if isVSTS or re.search(r"\.git(?:#.+)?$", lower_source_location):
230+
# git url must contain ".git" or be from VSTS/Azure DevOps.
231+
# This is because Azure DevOps doesn't follow the standard git server convention of putting
232+
# .git at the end of their URLs, so we have to special case them.
233+
return source_location
234+
if not lower_source_location.startswith("github.com/"):
235+
# Others are tarball
236+
if requests.head(source_location).status_code < 400:
237+
return source_location
238+
raise CLIInternalError("'{}' doesn't exist.".format(source_location))
239+
240+
# oci
241+
if lower_source_location.startswith("oci://"):
242+
return source_location
243+
raise CLIInternalError("'{}' doesn't exist.".format(source_location))

0 commit comments

Comments
 (0)