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
30 changes: 30 additions & 0 deletions src/azure-cli/azure/cli/command_modules/resource/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -2787,6 +2787,18 @@
text: az bicep build --file {bicep_file} --no-restore
"""

helps['bicep build-params'] = """
type: command
short-summary: Build .bicepparam file.
examples:
- name: Build a .bicepparam file.
text: az bicep build-params --file {bicepparam_file}
- name: Build a .bicepparam file and print all output to stdout.
text: az bicep build-params --file {bicepparam_file} --stdout
- name: Build a .bicepparam file and save the result to the specified file.
text: az bicep build-params --file {bicepparam_file} --outfile {out_file}
"""

helps['bicep format'] = """
type: command
short-summary: Format a Bicep file.
Expand Down Expand Up @@ -2817,6 +2829,22 @@
text: az bicep decompile --file {json_template_file} --force
"""

helps['bicep decompile-params'] = """
type: command
short-summary: Decompile a parameters .json file to .bicepparam.
examples:
- name: Attempts to decompile a parameters .json file to .bicepparam.
text: az bicep decompile-params --file {json_template_file}
- name: Attempts to decompile a parameters .json file to .bicepparam using the bicep file given.
text: az bicep decompile-params --file {json_template_file} --bicep-file {bicep_file}
- name: Attempts to decompile a parameters .json file to .bicepparam and print all output to stdout.
text: az bicep decompile-params --file {json_template_file} --stdout
- name: Attempts to decompile a parameters .json file to .bicepparam and print all output to stdout and save the result to the specified directory.
text: az bicep decompile-params --file {json_template_file} --outdir {out_dir}
- name: Attempts to decompile a parameters .json file to .bicepparam and print all output to stdout and save the result to the specified file.
text: az bicep decompile-params --file {json_template_file} --outfile {out_file}
"""

helps['bicep publish'] = """
type: command
short-summary: Publish a bicep file to a remote module registry.
Expand Down Expand Up @@ -3070,6 +3098,8 @@
text: az bicep generate-params --file {bicep_file} --outfile {out_file}
- name: Generate parameters file for a Bicep file without restoring external modules.
text: az bicep generate-params --file {bicep_file} --no-restore
- name: Generate parameters file for a Bicep file with specified output format. Valid values are ( json | bicepparam ).
text: az bicep generate-params --file {bicep_file} --output-format {output_format} --include-params {include_params}
"""

helps['resourcemanagement'] = """
Expand Down
17 changes: 17 additions & 0 deletions src/azure-cli/azure/cli/command_modules/resource/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -806,6 +806,13 @@ def load_arguments(self, _):
c.argument('stdout', arg_type=bicep_stdout_type)
c.argument('no_restore', arg_type=bicep_no_restore_type, help="When set, builds the bicep file without restoring external modules.")

with self.argument_context('bicep build-params') as c:
c.argument('file', arg_type=bicep_file_type, help="The path to the .bicepparam file to build in the file system.")
c.argument('outdir', arg_type=bicep_outdir_type)
c.argument('outfile', arg_type=bicep_outfile_type)
c.argument('stdout', arg_type=bicep_stdout_type)
c.argument('no_restore', arg_type=bicep_no_restore_type, help="When set, builds the .bicepparam file without restoring external modules.")

with self.argument_context('bicep format') as c:
c.argument('file', arg_type=bicep_file_type, help="The path to the Bicep file to format in the file system.")
c.argument('outdir', arg_type=bicep_outdir_type)
Expand All @@ -820,6 +827,14 @@ def load_arguments(self, _):
c.argument('file', arg_type=bicep_file_type, help="The path to the ARM template to decompile in the file system.")
c.argument('force', arg_type=bicep_force_type, help="Allows overwriting the output file if it exists.")

with self.argument_context('bicep decompile-params') as c:
c.argument('file', arg_type=bicep_file_type, help="The path to the parameters file to build in the file system.")
c.argument('bicep_file', completer=FilesCompleter(), type=file_type, help="Path to the bicep template file (relative to the .bicepparam file) that will be referenced in the using declaration.")
c.argument('outdir', arg_type=bicep_outdir_type)
c.argument('outfile', arg_type=bicep_outfile_type)
c.argument('stdout', arg_type=bicep_stdout_type)
c.argument('force', arg_type=bicep_force_type, help="Allows overwriting the output file if it exists.")

with self.argument_context('bicep restore') as c:
c.argument('file', arg_type=bicep_file_type, help="The path to the Bicep file to restore external modules for.")
c.argument('force', arg_type=bicep_force_type, help="Allows overwriting the cached external modules.")
Expand All @@ -845,6 +860,8 @@ def load_arguments(self, _):
c.argument('outfile', arg_type=bicep_outfile_type)
c.argument('stdout', arg_type=bicep_stdout_type)
c.argument('no_restore', arg_type=bicep_no_restore_type, help="When set, generates the parameters file without restoring external modules.")
c.argument('output_format', help="Set output format. Valid values are ( json | bicepparam ).")
c.argument('include_params', help="Set include params. Valid values are ( all | required-only ).")

with self.argument_context('resourcemanagement private-link create') as c:
c.argument('resource_group', arg_type=resource_group_name_type,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -608,8 +608,10 @@ def load_command_table(self, _):
g.custom_command('uninstall', 'uninstall_bicep_cli')
g.custom_command('upgrade', 'upgrade_bicep_cli')
g.custom_command('build', 'build_bicep_file')
g.custom_command('build-params', 'build_bicepparam_file')
g.custom_command('format', 'format_bicep_file')
g.custom_command('decompile', 'decompile_bicep_file')
g.custom_command('decompile-params', 'decompileparams_bicep_file')
g.custom_command('restore', 'restore_bicep_file')
g.custom_command('publish', 'publish_bicep_file')
g.custom_command('version', 'show_bicep_cli_version')
Expand Down
46 changes: 45 additions & 1 deletion src/azure-cli/azure/cli/command_modules/resource/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -4282,6 +4282,23 @@ def build_bicep_file(cmd, file, stdout=None, outdir=None, outfile=None, no_resto
print(output)


def build_bicepparam_file(cmd, file, stdout=None, outdir=None, outfile=None, no_restore=None):
args = ["build-params", file]
if outdir:
args += ["--outdir", outdir]
if outfile:
args += ["--outfile", outfile]
if no_restore:
args += ["--no-restore"]
if stdout:
args += ["--stdout"]

output = run_bicep_command(cmd.cli_ctx, args)

if stdout:
print(output)


def format_bicep_file(cmd, file, stdout=None, outdir=None, outfile=None, newline=None, indent_kind=None, indent_size=None, insert_final_newline=None):
ensure_bicep_installation(cmd.cli_ctx)

Expand Down Expand Up @@ -4354,6 +4371,29 @@ def decompile_bicep_file(cmd, file, force=None):
run_bicep_command(cmd.cli_ctx, args)


def decompileparams_bicep_file(cmd, file, bicep_file=None, outdir=None, outfile=None, stdout=None):
ensure_bicep_installation(cmd.cli_ctx)

minimum_supported_version = "0.18.4"
if bicep_version_greater_than_or_equal_to(minimum_supported_version):
args = ["decompile-params", file]
if bicep_file:
args += ["--bicep-file", bicep_file]
if outdir:
args += ["--outdir", outdir]
if outfile:
args += ["--outfile", outfile]
if stdout:
args += ["--stdout"]

output = run_bicep_command(cmd.cli_ctx, args)

if stdout:
print(output)
else:
logger.error("az bicep decompile-params could not be executed with the current version of Bicep CLI. Please upgrade Bicep CLI to v%s or later.", minimum_supported_version)


def show_bicep_cli_version(cmd):
print(run_bicep_command(cmd.cli_ctx, ["--version"], auto_install=False))

Expand All @@ -4362,7 +4402,7 @@ def list_bicep_cli_versions(cmd):
return get_bicep_available_release_tags()


def generate_params_file(cmd, file, no_restore=None, outdir=None, outfile=None, stdout=None):
def generate_params_file(cmd, file, no_restore=None, outdir=None, outfile=None, stdout=None, output_format=None, include_params=None):
ensure_bicep_installation(cmd.cli_ctx)

minimum_supported_version = "0.7.4"
Expand All @@ -4374,6 +4414,10 @@ def generate_params_file(cmd, file, no_restore=None, outdir=None, outfile=None,
args += ["--outdir", outdir]
if outfile:
args += ["--outfile", outfile]
if output_format:
args += ["--output-format", output_format]
if include_params:
args += ["--include-params", include_params]
if stdout:
args += ["--stdout"]

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using './sample_params.bicep'

param demoString = ''
param demoInt = 0
param demoBool = false
param demoObject = {}
param demoArray = []

Original file line number Diff line number Diff line change
Expand Up @@ -4987,6 +4987,66 @@ def test_bicep_list_versions(self):
self.greater_than('length(@)', 0)
])

class BicepDecompileParamsTest(ScenarioTest):
def setup(self):
super().setup()
self.cmd('az bicep uninstall')

def tearDown(self):
super().tearDown()
self.cmd('az bicep uninstall')

def test_bicep_decompile_params_file(self):
curr_dir = os.path.dirname(os.path.realpath(__file__))
tf = os.path.join(curr_dir, 'test-params.json').replace('\\', '\\\\')
params_path = os.path.join(curr_dir, 'test-params.bicepparam').replace('\\', '\\\\')
self.kwargs.update({
'tf': tf,
'params_path': params_path,
})

self.cmd('az bicep decompile-params --file {tf}')

if os.path.exists(params_path):
os.remove(params_path)

class BicepBuildParamsTest(ScenarioTest):
def setup(self):
super().setup()
self.cmd('az bicep uninstall')

def tearDown(self):
super().tearDown()
self.cmd('az bicep uninstall')

def test_bicep_build_params_file(self):
curr_dir = os.path.dirname(os.path.realpath(__file__))
tf = os.path.join(curr_dir, 'sample_params.bicepparam').replace('\\', '\\\\')
params_path = os.path.join(curr_dir, 'sample_params.parameters.json').replace('\\', '\\\\')
self.kwargs.update({
'tf': tf,
'params_path': params_path,
})

self.cmd('az bicep build-params --file {tf}')

if os.path.exists(params_path):
os.remove(params_path)

def test_bicep_build_params_file_outfile(self):
curr_dir = os.path.dirname(os.path.realpath(__file__))
tf = os.path.join(curr_dir, 'sample_params.bicepparam').replace('\\', '\\\\')
params_path = os.path.join(curr_dir, 'sample_params.parameters.json').replace('\\', '\\\\')
self.kwargs.update({
'tf': tf,
'params_path': params_path,
})

self.cmd('az bicep build-params --file {tf} --outfile {params_path}')

if os.path.exists(params_path):
os.remove(params_path)

# Because don't want to record bicep cli binary
class BicepBuildTest(LiveScenarioTest):

Expand Down Expand Up @@ -5019,7 +5079,6 @@ def test_bicep_build_decompile(self):
os.remove(decompile_path)

class BicepGenerateParamsTest(LiveScenarioTest):

def setup(self):
super().setup()
self.cmd('az bicep uninstall')
Expand All @@ -5028,6 +5087,34 @@ def tearDown(self):
super().tearDown()
self.cmd('az bicep uninstall')

def test_bicep_generate_params_output_format_only(self):
curr_dir = os.path.dirname(os.path.realpath(__file__))
tf = os.path.join(curr_dir, 'sample_params.bicep').replace('\\', '\\\\')
params_path = os.path.join(curr_dir, 'sample_params.parameters.json').replace('\\', '\\\\')
self.kwargs.update({
'tf': tf,
'params_path': params_path,
})

self.cmd('az bicep generate-params -f {tf} --outfile {params_path} --output-format json')

if os.path.exists(params_path):
os.remove(params_path)

def test_bicep_generate_params_include_params_only(self):
curr_dir = os.path.dirname(os.path.realpath(__file__))
tf = os.path.join(curr_dir, 'sample_params.bicep').replace('\\', '\\\\')
params_path = os.path.join(curr_dir, 'sample_params.parameters.json').replace('\\', '\\\\')
self.kwargs.update({
'tf': tf,
'params_path': params_path,
})

self.cmd('az bicep generate-params -f {tf} --outfile {params_path} --include-params all')

if os.path.exists(params_path):
os.remove(params_path)

def test_bicep_generate_params(self):
curr_dir = os.path.dirname(os.path.realpath(__file__))
tf = os.path.join(curr_dir, 'sample_params.bicep').replace('\\', '\\\\')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
format_bicep_file,
)

from azure.cli.command_modules.resource._bicep import (run_bicep_command)

from azure.cli.core.mock import DummyCli
from azure.cli.core import AzCommandsLoader
from azure.cli.core.commands import AzCliCommand
Expand Down Expand Up @@ -339,6 +341,7 @@ def test_deployment_prompt_file_order(self):
def test_deployment_prompt_alphabetical_order(self):
# check that params are prompted for in alphabetical order when the file is loaded with preserve_order=False
curr_dir = os.path.dirname(os.path.realpath(__file__))

template_path = os.path.join(curr_dir, 'param-validation-template.json').replace('\\', '\\\\')
parameters_path = os.path.join(curr_dir, 'param-validation-params.json').replace('\\', '\\\\')
parameters_with_reference_path = os.path.join(curr_dir, 'param-validation-ref-params.json').replace('\\', '\\\\')
Expand All @@ -362,6 +365,53 @@ def test_deployment_bicepparam_file_input_check(self):
self.assertEqual(_is_bicepparam_file_provided([['test.bicepparam']]), True)
self.assertEqual(_is_bicepparam_file_provided([['test.bicepparam'], ['test.json'], ['{ \"foo\": { \"value\": \"bar\" } }']]), True)

def test_bicep_generate_params_defaults(self):
curr_dir = os.path.dirname(os.path.realpath(__file__))
bicep_file = os.path.join(curr_dir, 'sample_params.bicep').replace('\\', '\\\\')
json_file = os.path.join(curr_dir, 'sample_params.parameters.json').replace('\\', '\\\\')

run_bicep_command(cli_ctx, ["generate-params", bicep_file])
is_generated_params_file_exists = os.path.exists(json_file)
self.assertTrue(is_generated_params_file_exists)

def test_bicep_generate_params_output_format(self):
curr_dir = os.path.dirname(os.path.realpath(__file__))
bicep_file = os.path.join(curr_dir, 'sample_params.bicep').replace('\\', '\\\\')
json_file = os.path.join(curr_dir, 'sample_params.parameters.json').replace('\\', '\\\\')

run_bicep_command(cli_ctx, ["generate-params", bicep_file, "--output-format", "json"])
is_generated_params_file_exists = os.path.exists(json_file)
self.assertTrue(is_generated_params_file_exists)

def test_bicep_generate_params_include_params(self):
curr_dir = os.path.dirname(os.path.realpath(__file__))
bicep_file = os.path.join(curr_dir, 'sample_params.bicep').replace('\\', '\\\\')
json_file = os.path.join(curr_dir, 'sample_params.parameters.json').replace('\\', '\\\\')

run_bicep_command(cli_ctx, ["generate-params", bicep_file, "--include-params", "all"])
is_generated_params_file_exists = os.path.exists(json_file)
self.assertTrue(is_generated_params_file_exists)

def test_bicep_build_params_defaults(self):
curr_dir = os.path.dirname(os.path.realpath(__file__))
param_file = os.path.join(curr_dir, 'sample_params.bicepparam').replace('\\', '\\\\')
json_file = os.path.join(curr_dir, 'sample_params.json').replace('\\', '\\\\')

run_bicep_command(cli_ctx, ["build-params", param_file])
is_generated_params_file_exists = os.path.exists(json_file)

self.assertTrue(is_generated_params_file_exists)

def test_bicep_decompile_params_defaults(self):
curr_dir = os.path.dirname(os.path.realpath(__file__))
param_file = os.path.join(curr_dir, 'param-validation-params.bicepparam').replace('\\', '\\\\')
json_file = os.path.join(curr_dir, 'param-validation-params.json').replace('\\', '\\\\')

run_bicep_command(cli_ctx, ["decompile-params", json_file, "--force"])
is_generated_params_file_exists = os.path.exists(param_file)

self.assertTrue(is_generated_params_file_exists)

@mock.patch("knack.prompting.prompt_y_n", autospec=True)
@mock.patch("azure.cli.command_modules.resource.custom._what_if_deploy_arm_template_at_resource_group_core", autospec=True)
def test_confirm_with_what_if_prompt_at_resource_group(self, what_if_command_mock, prompt_y_n_mock):
Expand Down Expand Up @@ -556,7 +606,8 @@ def test_format_bicep_file(self, mock_print, mock_run_bicep_command, mock_bicep_

# Assert.
mock_bicep_version_greater_than_or_equal_to.assert_called_once_with("0.12.1")
mock_run_bicep_command.assert_called_once_with(cmd.cli_ctx, ["format", file_path, "--stdout"])

mock_run_bicep_command.assert_called_once_with(cmd.cli_ctx, ["format", file_path, "--stdout"])


if __name__ == '__main__':
unittest.main()