Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Compute] az image builder: Add parameter --staging-resource-group in create command to support custom resource group naming and add subgroup validator to manage validate information of template #23303

Merged
merged 5 commits into from
Jul 25, 2022
Merged
Show file tree
Hide file tree
Changes from 3 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
89 changes: 67 additions & 22 deletions src/azure-cli/azure/cli/command_modules/vm/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -363,19 +363,19 @@
- az vm image list
- az vm image show
examples:
- name: Create an image builder template from an UbuntuLTS 18.04 image. Distribute it as a managed image and a shared image gallery image version
- name: Create an image builder template from an UbuntuLTS 18.04 image. Distribute it as a managed image and a shared image gallery image version. Specify the staging resource group id as the image template that will be used to build the image.
text: |
scripts="https://my-script-url.net/customize_script.sh"
imagesource="Canonical:UbuntuServer:18.04-LTS:18.04.201903060"

az image builder create --image-source $imagesource -n mytemplate -g my-group \\
az image builder create --image-source $imagesource -n myTemplate -g myGroup \\
--scripts $scripts --managed-image-destinations image_1=westus \\
--shared-image-destinations my_shared_gallery/linux_image_def=westus,brazilsouth \\
--identity myidentity
--identity myIdentity --staging-resource-group myStagingResourceGroup

- name: Create an image builder template using an image template file.
text: |
az image builder create -g my-group -n mytemplate --image-template filename
az image builder create -g my-group -n myTemplate --image-template filename

- name: >
[Advanced] Create an image template with multiple customizers and distributors using the CLI's object cache via --defer. Supports features such as: customizer and output names, powershell exit codes, inline scripts, windows restart, file customizers, artifact tags and vhd output distributors.
Expand All @@ -385,32 +385,32 @@

# create and update template object in local cli cache. Defers put request to ARM
# Cache object ttl set via az configure.
az image builder create --image-source $imagesource -n mytemplate \\
-g my-group --scripts $script --identity myidentity --defer
az image builder create --image-source $imagesource -n myTemplate \\
-g myGroup --scripts $script --identity myIdentity --defer

# add customizers
az image builder customizer add -n mytemplate -g my-group \\
--customizer-name my-pwsh-script --exit-codes 0 1 --inline-script \\
az image builder customizer add -n myTemplate -g myGroup \\
--customizer-name myPwshScript --exit-codes 0 1 --inline-script \\
"mkdir c:\\buildActions" "echo Azure-Image-Builder-Was-Here \\
> c:\\buildActions\\Output.txt" --type powershell --defer

az image builder customizer add -n mytemplate -g my-group \\
--customizer-name my-file-customizer --type file \\
az image builder customizer add -n myTemplate -g myGroup \\
--customizer-name myFileCustomizer --type file \\
--file-source "https://my-file-source.net/file.txt" \\
--dest-path "c:\\buildArtifacts\\file.txt" --defer

# add distributors
az image builder output add -n mytemplate -g my-group --is-vhd \\
--output-name my-win-image-vhd --artifact-tags "is_vhd=True" --defer
az image builder output add -n myTemplate -g myGroup --is-vhd \\
--output-name myWinImageVhd --artifact-tags "is_vhd=True" --defer

az image builder output add -n mytemplate -g my-group \\
--output-name my-win-image-managed --managed-image winImage \\
az image builder output add -n myTemplate -g myGroup \\
--output-name myWinImageManaged --managed-image winImage \\
--managed-image-location eastus \\
--artifact-tags "is_vhd=False" --defer

# Stop deferring put request to ARM. Create the template from the object cache.
# Cache object will be deleted.
az image builder update -n mytemplate -g my-group
az image builder update -n myTemplate -g myGroup
"""

helps['image builder customizer'] = """
Expand All @@ -425,28 +425,28 @@
examples:
- name: Add an inline shell customizer to an image template in the cli object cache
text: |
az image builder customizer add -n mytemplate -g my-group \\
az image builder customizer add -n myTemplate -g myGroup \\
--inline-script "sudo mkdir /buildArtifacts" \\
"sudo cp /tmp/index.html /buildArtifacts/index.html" \\
--customizer-name shell-script-inline --type shell --defer
--customizer-name shellScriptInline --type shell --defer

- name: Add a file customizer to an image template in the cli object cache
text: |
az image builder customizer add -n mytemplate -g my-group \\
--customizer-name my-file --type file \\
az image builder customizer add -n myTemplate -g myGroup \\
--customizer-name myFile --type file \\
--file-source "https://my-remote-file.html" --dest-path "/tmp/index.html" --defer

- name: Add a windows restart customizer to an image template in the cli object cache
text: |
az image builder customizer add -n mytemplate -g my-group \\
--customizer-name shell-script-url \\
az image builder customizer add -n myTemplate -g myGroup \\
--customizer-name shellScriptUrl \\
--restart-check-command "echo Azure-Image-Builder-Restarted-the-VM > \\
c:\\buildArtifacts\\restart.txt" \\
--type windows-restart --restart-timeout 10m --defer

- name: Add a windows update customizer to an image template in the cli object cache.
text: |
az image builder customizer add -n mytemplate -g my-group --customizer-name win_update --type windows-update --search-criteria IsInstalled=0 --filters "exclude:\\$_.Title -like \\'*Preview*\\'" "include:\\$true" --update-limit 20 --defer
az image builder customizer add -n myTemplate -g myGroup --customizer-name winUpdate --type windows-update --search-criteria IsInstalled=0 --filters "exclude:\\$_.Title -like \\'*Preview*\\'" "include:\\$true" --update-limit 20 --defer
"""

helps['image builder customizer clear'] = """
Expand All @@ -461,6 +461,51 @@
long-summary: Must be used with --defer
"""

helps['image builder validator'] = """
type: group
short-summary: Manage image builder template validate.
"""

helps['image builder validator add'] = """
type: command
short-summary: Add validate to an existing image builder template.
long-summary: Must be used with --defer
Copy link
Contributor

Choose a reason for hiding this comment

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

May I ask why do these commands have to be used with --defer?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

May I ask why do these commands have to be used with --defer?

It seems that the update operation (update an existing image template) is not supported in service side, so the parameter --defer is used to support managing validate in local cache, and then customer can choose to update the local cache to service to get the actual resource.

Copy link
Contributor

Choose a reason for hiding this comment

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

Got it, thanks~

examples:
- name: Add validate with continue distribute on failure set to true. If not specified, the default value of continue distribute on failure is false.
If validation fails and this field is set to false, output image(s) will not be distributed.
text: |
az image builder validator add -n myTemplate -g myGroup --continue-distribute-on-failure true --defer

- name: Add validate with source validation only set to true. If not specified, the default value of source validation only is false.
If this field is set to true, the image specified in the source section will directly be validated.
text: |
az image builder validator add -n myTemplate -g myGroup --source-validation-only true --defer

- name: Add validate with source validation only and continue distribute on failure set to false.
text: |
az image builder validator add -n myTemplate -g myGroup --defer
"""

helps['image builder validator remove'] = """
type: command
short-summary: Remove validate from an existing image builder template.
long-summary: Must be used with --defer
examples:
- name: Remove validate from an existing image builder template.
text: |
az image builder validator remove -n myTemplate -g myGroup --defer
"""

helps['image builder validator show'] = """
type: command
short-summary: Show validate of an existing image builder template.
long-summary: Must be used with --defer
examples:
- name: Show validate of an existing image builder template.
text: |
az image builder validator show -n myTemplate -g myGroup --defer
"""

helps['image builder delete'] = """
type: command
short-summary: Delete image builder template.
Expand Down
56 changes: 52 additions & 4 deletions src/azure-cli/azure/cli/command_modules/vm/_image_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
from azure.cli.core.commands import cached_get, cached_put
from azure.cli.core.commands.client_factory import get_subscription_id
from azure.cli.core.commands.validators import get_default_location_from_resource_group, validate_tags
from azure.cli.core.azclierror import RequiredArgumentMissingError
from azure.cli.core.azclierror import RequiredArgumentMissingError, ResourceNotFoundError

from azure.cli.command_modules.vm._client_factory import _compute_client_factory
from azure.cli.command_modules.vm._validators import _get_resource_id
Expand Down Expand Up @@ -394,7 +394,8 @@ def create_image_template( # pylint: disable=too-many-locals, too-many-branches
source_dict=None, scripts_list=None, destinations_lists=None, build_timeout=None, tags=None,
source=None, scripts=None, checksum=None, managed_image_destinations=None,
shared_image_destinations=None, no_wait=False, image_template=None, identity=None,
vm_size=None, os_disk_size=None, vnet=None, subnet=None, proxy_vm_size=None, build_vm_identities=None):
vm_size=None, os_disk_size=None, vnet=None, subnet=None, proxy_vm_size=None, build_vm_identities=None,
staging_resource_group=None):
from azure.mgmt.imagebuilder.models import (ImageTemplate, ImageTemplateSharedImageVersionSource,
ImageTemplatePlatformImageSource, ImageTemplateManagedImageSource,
ImageTemplateShellCustomizer, ImageTemplatePowerShellCustomizer,
Expand Down Expand Up @@ -434,6 +435,8 @@ def create_image_template( # pylint: disable=too-many-locals, too-many-branches
content['tags'] = obj['tags']
if 'identity' in obj:
content['identity'] = obj['identity']
if 'staging_resource_group' in obj:
content['staging_resource_group'] = obj['staging_resource_group']
return client.virtual_machine_image_templates.begin_create_or_update(
parameters=content, resource_group_name=resource_group_name, image_template_name=image_template_name)

Expand Down Expand Up @@ -504,9 +507,13 @@ def create_image_template( # pylint: disable=too-many-locals, too-many-branches
raise RequiredArgumentMissingError('Usage error: --proxy-vm-size is only configurable when --subnet is specified.')
vm_profile = ImageTemplateVmProfile(vm_size=vm_size, os_disk_size_gb=os_disk_size, user_assigned_identities=build_vm_identities, vnet_config=vnet_config) # pylint: disable=line-too-long

image_template = ImageTemplate(source=template_source, customize=template_scripts, distribute=template_destinations,
image_template = ImageTemplate(source=template_source, distribute=template_destinations,
location=location, build_timeout_in_minutes=build_timeout, tags=(tags or {}),
identity=identity_body, vm_profile=vm_profile)
identity=identity_body, vm_profile=vm_profile,
staging_resource_group=staging_resource_group)

if len(template_scripts) > 0:
image_template.customize = template_scripts

return cached_put(cmd, client.virtual_machine_image_templates.begin_create_or_update, parameters=image_template,
resource_group_name=resource_group_name, image_template_name=image_template_name)
Expand Down Expand Up @@ -696,4 +703,45 @@ def clear_template_customizer(cmd, client, resource_group_name, image_template_n
return cached_put(cmd, client.virtual_machine_image_templates.begin_create_or_update, parameters=existing_image_template, # pylint: disable=line-too-long
resource_group_name=resource_group_name, image_template_name=image_template_name)


def add_template_validator(cmd, client, resource_group_name, image_template_name,
dis_on_failure=False, source_validation_only=False):
_require_defer(cmd)
from azure.mgmt.imagebuilder.models import ImageTemplatePropertiesValidate

existing_image_template = cached_get(cmd, client.virtual_machine_image_templates.get,
resource_group_name=resource_group_name,
image_template_name=image_template_name)
image_template_properties_validate = ImageTemplatePropertiesValidate(
continue_distribute_on_failure=dis_on_failure, source_validation_only=source_validation_only)
existing_image_template.validate = image_template_properties_validate

return cached_put(cmd, client.virtual_machine_image_templates.begin_create_or_update,
parameters=existing_image_template, resource_group_name=resource_group_name,
image_template_name=image_template_name)


def remove_template_validator(cmd, client, resource_group_name, image_template_name):
_require_defer(cmd)
existing_image_template = cached_get(cmd, client.virtual_machine_image_templates.get,
resource_group_name=resource_group_name,
image_template_name=image_template_name)

if not existing_image_template.validate:
raise ResourceNotFoundError("No validate existing in this image template, no need to remove.")

existing_image_template.validate = None

return cached_put(cmd, client.virtual_machine_image_templates.begin_create_or_update, parameters=existing_image_template, # pylint: disable=line-too-long
resource_group_name=resource_group_name, image_template_name=image_template_name)


def show_template_validator(cmd, client, resource_group_name, image_template_name):
_require_defer(cmd)

existing_image_template = cached_get(cmd, client.virtual_machine_image_templates.get,
resource_group_name=resource_group_name,
image_template_name=image_template_name)
return existing_image_template.validate

# endregion
4 changes: 4 additions & 0 deletions src/azure-cli/azure/cli/command_modules/vm/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,7 @@ def load_arguments(self, _):
c.argument('build_timeout', type=int, help="The Maximum duration to wait while building the image template, in minutes. Default is 60.")
c.argument('image_template', help='Local path or URL to an image template file. When using --image-template, all other parameters are ignored except -g and -n. Reference: https://docs.microsoft.com/azure/virtual-machines/linux/image-builder-json')
c.argument('identity', nargs='+', help='List of user assigned identities (name or ID, space delimited) of the image template.')
c.argument('staging_resource_group', min_api='2022-02-14', help='The staging resource group id in the same subscription as the image template that will be used to build the image.')

# VM profile
c.argument('vm_size', help='Size of the virtual machine used to build, customize and capture images. Omit or specify empty string to use the default (Standard_D1_v2)')
Expand Down Expand Up @@ -350,6 +351,9 @@ def load_arguments(self, _):
c.argument('file_source', arg_type=ib_file_customizer_type, help="The URI of the file to be downloaded into the image. It can be a github link, SAS URI for Azure Storage, etc.")
c.argument('dest_path', arg_type=ib_file_customizer_type, help="The absolute destination path where the file specified in --file-source will be downloaded to in the image")

with self.argument_context('image builder validator add', min_api='2022-02-14') as c:
c.argument('dis_on_failure', options_list=['--continue-distribute-on-failure', '--dis-on-failure'], arg_type=get_three_state_flag(), help="If validation fails and this field is set to false, output image(s) will not be distributed.")
c.argument('source_validation_only', arg_type=get_three_state_flag(), help="If this field is set to true, the image specified in the 'source' section will directly be validated. No separate build will be run to generate and then validate a customized image.")
zhoxing-ms marked this conversation as resolved.
Show resolved Hide resolved
# endregion

# region AvailabilitySets
Expand Down
5 changes: 5 additions & 0 deletions src/azure-cli/azure/cli/command_modules/vm/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,11 @@ def load_command_table(self, _):
g.custom_command('remove', 'remove_template_output', supports_local_cache=True)
g.custom_command('clear', 'clear_template_output', supports_local_cache=True)

with self.command_group('image builder validator', image_builder_image_templates_sdk, custom_command_type=image_builder_custom) as g:
g.custom_command('add', 'add_template_validator', supports_local_cache=True)
g.custom_command('remove', 'remove_template_validator', supports_local_cache=True)
g.custom_show_command('show', 'show_template_validator', supports_local_cache=True)

with self.command_group('snapshot', compute_snapshot_sdk, operation_group='snapshots', min_api='2016-04-30-preview') as g:
g.custom_command('create', 'create_snapshot', validator=process_snapshot_create_namespace, supports_no_wait=True)
g.command('delete', 'begin_delete')
Expand Down
Loading