Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file not shown.
1 change: 1 addition & 0 deletions src/command_modules/azure-cli-acr/HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Release History

2.0.24
++++++
* Add ACR Build commands.
* Improve resource not found error messages.
* Improve resource creation performance and error handling.
* Improve acr login in non-standard consoles and WSL.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ def get_storage_service_client(cli_ctx):
return get_mgmt_service_client(cli_ctx, ResourceType.MGMT_STORAGE)


def get_acr_service_client(cli_ctx, api_version=None):
def get_acr_service_client(cli_ctx, api_version='2018-02-01-preview'):
"""Returns the client for managing container registries. """
from azure.mgmt.containerregistry import ContainerRegistryManagementClient
return get_mgmt_service_client(cli_ctx, ContainerRegistryManagementClient, api_version=api_version)
Expand All @@ -34,3 +34,15 @@ def cf_acr_replications(cli_ctx, *_):

def cf_acr_webhooks(cli_ctx, *_):
return get_acr_service_client(cli_ctx).webhooks


def cf_acr_builds(cli_ctx, *_):
return get_acr_service_client(cli_ctx).builds


def cf_acr_build_tasks(cli_ctx, *_):
return get_acr_service_client(cli_ctx).build_tasks


def cf_acr_build_steps(cli_ctx, *_):
return get_acr_service_client(cli_ctx).build_steps
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
REGISTRY_RESOURCE_TYPE = ACR_RESOURCE_PROVIDER + '/registries'
WEBHOOK_RESOURCE_TYPE = REGISTRY_RESOURCE_TYPE + '/webhooks'
REPLICATION_RESOURCE_TYPE = REGISTRY_RESOURCE_TYPE + '/replications'
BUILD_TASK_RESOURCE_TYPE = REGISTRY_RESOURCE_TYPE + '/buildTasks'
BUILD_STEP_RESOURCE_TYPE = BUILD_TASK_RESOURCE_TYPE + '/steps'

CLASSIC_REGISTRY_SKU = ['Classic']
MANAGED_REGISTRY_SKU = ['Basic', 'Standard', 'Premium']
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
# --------------------------------------------------------------------------------------------

from collections import OrderedDict
from knack.log import get_logger


logger = get_logger(__name__)


def registry_output_format(result):
Expand Down Expand Up @@ -38,6 +42,18 @@ def replication_output_format(result):
return _output_format(result, _replication_format_group)


def build_task_output_format(result):
return _output_format(result, _build_task_format_group)


def build_task_detail_output_format(result):
return _output_format(result, _build_task_detail_format_group)


def build_output_format(result):
return _output_format(result, _build_format_group)


def _output_format(result, format_group):
if 'value' in result and isinstance(result['value'], list):
result = result['value']
Expand Down Expand Up @@ -121,12 +137,40 @@ def _replication_format_group(item):
])


def _format_datetime(date_string):
from dateutil.parser import parse
try:
return parse(date_string).strftime("%Y-%m-%dT%H:%M:%SZ")
except ValueError:
return date_string or ' '
def _build_task_format_group(item):
return OrderedDict([
('Name', _get_value(item, 'name')),
('PLATFORM', _get_value(item, 'platform', 'osType')),
('STATUS', _get_value(item, 'status')),
('COMMIT TRIGGER', _get_value(item, 'sourceRepository', 'isCommitTriggerEnabled')),
('SOURCE REPOSITORY', _get_value(item, 'sourceRepository', 'repositoryUrl'))
])


def _build_task_detail_format_group(item):
return OrderedDict([
('Name', _get_value(item, 'name')),
('PLATFORM', _get_value(item, 'platform', 'osType')),
('STATUS', _get_value(item, 'status')),
('COMMIT TRIGGER', _get_value(item, 'sourceRepository', 'isCommitTriggerEnabled')),
('SOURCE REPOSITORY', _get_value(item, 'sourceRepository', 'repositoryUrl')),
('BRANCH', _get_value(item, 'properties', 'branch')),
('BASE IMAGE TRIGGER', _get_value(item, 'properties', 'baseImageTrigger')),
('IMAGE NAMES', _get_value(item, 'properties', 'imageNames')),
('PUSH ENABLED', _get_value(item, 'properties', 'isPushEnabled'))
])


def _build_format_group(item):
return OrderedDict([
('BUILD ID', _get_value(item, 'buildId')),
('TASK', _get_value(item, 'buildTask')),
('PLATFORM', _get_value(item, 'platform', 'osType')),
('STATUS', _get_value(item, 'status')),
("TRIGGER", _get_build_trigger(_get_value(item, 'imageUpdateTrigger'), _get_value(item, 'gitCommitTrigger'))),
('STARTED', _format_datetime(_get_value(item, 'startTime'))),
('DURATION', _get_duration(_get_value(item, 'startTime'), _get_value(item, 'finishTime')))
])


def _get_value(item, *args):
Expand All @@ -139,3 +183,33 @@ def _get_value(item, *args):
return str(item) if item else ' '
except (KeyError, TypeError, IndexError):
return ' '


def _get_build_trigger(image_update_trigger, git_commit_trigger):
if git_commit_trigger.strip():
return 'Git Commit'
if image_update_trigger.strip():
return 'Image Update'
return 'Manual'


def _format_datetime(date_string):
from dateutil.parser import parse
try:
return parse(date_string).strftime("%Y-%m-%dT%H:%M:%SZ")
except ValueError:
logger.debug("Unable to parse date_string '%s'", date_string)
return date_string or ' '
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why a debug message and potentially unexpected behavior rather than a CLIError?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have a few cases that the response doesn't have the datetime yet. For example, if users trigger a build and immediately get the status of it before it finishes, we don't have a finish time here. This is table formatting path and we thought we can just show empty in the column rather than throwing an error.



def _get_duration(start_time, finish_time):
from dateutil.parser import parse
try:
duration = parse(finish_time) - parse(start_time)
hours = "{0:02d}".format((24 * duration.days) + (duration.seconds // 3600))
minutes = "{0:02d}".format((duration.seconds % 3600) // 60)
seconds = "{0:02d}".format(duration.seconds % 60)
return "{0}:{1}:{2}".format(hours, minutes, seconds)
except ValueError:
logger.debug("Unable to get duration with start_time '%s' and finish_time '%s'", start_time, finish_time)
return ' '
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here--if the user inputs an invalid format, then failing silently and having unexpected behavior is probably not better than throwing an error.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the same reason as above handling response datetime. We don't format user inputs here. In this case, finish_time could be empty.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't notice this was for table format. Displaying blank is completely appropriate.

Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

helps['acr'] = """
type: group
short-summary: Manage Azure Container Registries.
short-summary: Manage Azure Container Registries for private registries within Azure.
"""

helps['acr credential'] = """
Expand All @@ -18,7 +18,7 @@

helps['acr repository'] = """
type: group
short-summary: Manage repositories for Azure Container Registries.
short-summary: Manage repositories (image names) for Azure Container Registries.
"""

helps['acr webhook'] = """
Expand All @@ -28,12 +28,17 @@

helps['acr replication'] = """
type: group
short-summary: Manage replications for Azure Container Registries.
short-summary: Manage replications of Azure Container Registries across multiple regions.
"""

helps['acr build-task'] = """
type: group
short-summary: Manage build definitions, which can be triggered by git commits or base image updates.
"""

helps['acr check-name'] = """
type: command
short-summary: Checks if a container registry name is available for use.
short-summary: Checks if a container registry name is valid and available for use.
examples:
- name: Check if a registry name already exists.
text: >
Expand Down Expand Up @@ -317,3 +322,110 @@
text: >
az acr replication update -n MyReplication -r MyRegistry --tags key1=value1 key2=value2
"""

helps['acr build-task create'] = """
type: command
short-summary: Creates a new build definition which can be triggered by git commits or base image updates.
examples:
- name: Create a build definition which updates on git commits and base image updates.
text: >
az acr build-task create -t helloworld:{{.Build.ID}} -n helloworld -r myRegistry -c https://github.com/Azure-Samples/acr-build-helloworld-node --git-access-token 0000000000000000000000000000000000000000
"""

helps['acr build-task show'] = """
type: command
short-summary: Get the properties of a specified build task.
examples:
- name: Get the details of a build task, displaying the results in a table.
text: >
az acr build-task show -n MyBuildTask -r MyRegistry -o table
"""

helps['acr build-task list'] = """
type: command
short-summary: List the build tasks for a container registry.
examples:
- name: List build tasks and show the results in a table.
text: >
az acr build-task list -r MyRegistry -o table
"""

helps['acr build-task delete'] = """
type: command
short-summary: Delete a build task from a container registry.
examples:
- name: Delete a build task from a container registry.
text: >
az acr build-task delete -n MyBuildTask -r MyRegistry
"""

helps['acr build-task update'] = """
type: command
short-summary: Update a build task for a container registry.
examples:
- name: Update the git access token for a build definition in a container registry.
text: >
az acr build-task update -n MyBuildTask -r MyRegistry --git-access-token 0000000000000000000000000000000000000000
"""

helps['acr build-task list-builds'] = """
type: command
short-summary: List all of the executed builds for a registry, with the ability to filter by a specific build task.
examples:
- name: List builds for a build task and show the results in a table.
text: >
az acr build-task list-builds -n MyBuildTask -r MyRegistry -o table
- name: List all of the builds for a registry and show the results in a table.
text: >
az acr build-task list-builds -r MyRegistry -o table
"""

helps['acr build-task show-build'] = """
type: command
short-summary: Get the properties of a specified build.
examples:
- name: Get the details of a build, displaying the results in a table.
text: >
az acr build-task show-build -n MyBuildTask -r MyRegistry --build-id MyBuild -o table
"""

helps['acr build-task run'] = """
type: command
short-summary: Trigger a build task that might otherwise be waiting for git commits or base image update triggers.
examples:
- name: Trigger a build task.
text: >
az acr build-task run -n MyBuildTask -r MyRegistry
"""

helps['acr build-task logs'] = """
type: command
short-summary: Show logs for a particular build. If no build-id is supplied, it shows logs for the last updated build.
examples:
- name: Show logs for the last updated build in the registry.
text: >
az acr build-task logs -r MyRegistry
- name: Show logs for the last updated build in the registry, filtered by build task.
text: >
az acr build-task logs -r MyRegistry -n MyBuildTask
- name: Show logs for a particular build.
text: >
az acr build-task logs -r MyRegistry --build-id buildId
"""

helps['acr build'] = """
type: command
short-summary: Queues a quick docker build providing interactive feedback.
examples:
- name: Queue a local context, pushed to ACR with streaming logs.
text: >
az acr build -t sample/helloworld:{{.Build.ID}} -r MyRegistry .
examples:
- name: Queue a local context, pushed to ACR without streaming logs.
text: >
az acr build -t sample/helloworld:{{.Build.ID}} -r MyRegistry --no-logs .
examples:
- name: Queue a local context, validating the build is successful, without pushing to the registry.
text: >
az acr build -r MyRegistry .
"""
Loading