Skip to content

Commit 9f64ce0

Browse files
authored
{vm-repair} Adding longoptions prefix to Run script Parameters (#8309)
1 parent 93fe9b0 commit 9f64ce0

File tree

6 files changed

+82
-4
lines changed

6 files changed

+82
-4
lines changed

src/vm-repair/HISTORY.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
Release History
33
===============
44

5+
2.0.3
6+
++++++
7+
Added new long parameter functionality in `vm repair run` cmd `parameters` parameter. When using the prefix `++`, the entire key=value string will be sent to the running script, not just the value.
8+
59
2.0.2
610
++++++
711
Updated parameter descriptions and examples for `az vm repair create`.

src/vm-repair/azext_vm_repair/_help.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@
6464
- name: Run a script with parameters on the VM.
6565
text: >
6666
az vm repair run -g MyResourceGroup -n MySourceWinVM --run-id win-hello-world --parameters hello=hi world=earth --verbose
67+
- name: Run a verified script with some parameters. In the first parameter named 'key', only the value 'test' is sent to the script. The second parameter named \'initiator\', uses the prefix '++' to send the entire following string 'initiator=selfhelp' to the script.
68+
text: >
69+
az vm repair run -g MyResourceGroup -n MySourceWinVM --run-id linux-alar2 --parameters key=test ++initiator=selfhelp --verbose --debug
6770
- name: Run a local custom script on the VM.
6871
text: >
6972
az vm repair run -g MyResourceGroup -n MySourceWinVM --custom-script-file ./file.ps1 --verbose

src/vm-repair/azext_vm_repair/_params.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ def load_arguments(self, _):
4545
c.argument('repair_vm_id', help='Repair VM resource id.')
4646
c.argument('run_id', help='Unique run id for run scripts.')
4747
c.argument('custom_script_file', help='Custom script file to run on VM. Script should be PowerShell for windows, Bash for Linux.')
48-
c.argument('parameters', nargs='+', help="Space-separated parameters in the format of '[name=]value'. Positional for bash scripts.")
48+
c.argument('parameters', nargs='+', help="Space-separated parameters in the format of '[name=]value'. Positional for bash scripts. To avoid splitting on =, use the prefix \'++\' to send the entire string.")
4949
c.argument('run_on_repair', help="Script will be run on the linked repair VM.")
5050
c.argument('preview', help="URL of forked repair script library's map.json https://github.com/{user}/repair-script-library/blob/master/map.json")
5151

@@ -71,4 +71,4 @@ def load_arguments(self, _):
7171
c.argument('copy_disk_name', help='Name of OS disk copy.')
7272
c.argument('repair_vm_name', help='Name of repair VM.')
7373
c.argument('copy_disk_name', help='Name of OS disk copy.')
74-
c.argument('repair_group_name', help='Name for new or existing resource group that will contain repair VM.')
74+
c.argument('repair_group_name', help='Name for new or existing resource group that will contain repair VM.')

src/vm-repair/azext_vm_repair/repair_utils.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -660,9 +660,15 @@ def _process_bash_parameters(parameters):
660660
Example: [param1=1, param2=2] => 1 2
661661
"""
662662
param_string = ''
663+
663664
for param in parameters:
664-
if '=' in param:
665+
if param.startswith("++"):
666+
# Retain the entire string after the `++` prefix
667+
param = param[2:]
668+
elif '=' in param:
669+
# Split and keep only the value after `=`
665670
param = param.split('=', 1)[1]
671+
# Ensure safe output for bash scripts
666672
param_string += '{p} '.format(p=param)
667673

668674
return param_string.strip(' ')

src/vm-repair/azext_vm_repair/tests/latest/test_repair_commands.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1128,6 +1128,7 @@ def test_vmrepair_DefaultGen1Image(self, resource_group):
11281128
# Call Restore
11291129
self.cmd('vm repair restore -g {rg} -n {vm} --yes')
11301130

1131+
11311132
@pytest.mark.RefactorSanityTest
11321133
class WindowsResourceIdParseAfterRefactor(LiveScenarioTest):
11331134

@@ -1179,3 +1180,67 @@ def test_vmrepair_WinRunRepairVMIdafterRefactor(self, resource_group):
11791180

11801181
# Call Restore
11811182
self.cmd('vm repair restore -g {rg} -n {vm} --yes')
1183+
1184+
1185+
@pytest.mark.linuxLongParams
1186+
class LinuxLongParametersParsing(LiveScenarioTest):
1187+
1188+
@ResourceGroupPreparer(location='westus2')
1189+
def test_vmrepair_LongoptionsParams(self, resource_group):
1190+
import uuid
1191+
import secrets
1192+
import string
1193+
base_password = "Passw0rd2024"
1194+
guid_suffix = str(uuid.uuid4())
1195+
secure_password = base_password + guid_suffix
1196+
# Username generation for linux
1197+
username_length = 8
1198+
allowed_characters = string.ascii_lowercase + string.digits # Only lowercase letters and digits
1199+
secure_username = ''.join(secrets.choice(allowed_characters) for _ in range(username_length))
1200+
1201+
# Ensure username doesn't start with "-" or "$"
1202+
while secure_username[0] in "-$":
1203+
secure_username = ''.join(secrets.choice(allowed_characters) for _ in range(username_length))
1204+
1205+
self.kwargs.update({
1206+
'vm': 'vm1',
1207+
'admin_password': secure_password,
1208+
'admin_username': secure_username
1209+
})
1210+
1211+
# Create test VM
1212+
self.cmd('vm create -g {rg} -n {vm} --admin-username {admin_username} --admin-password {admin_password} --image Canonical:0001-com-ubuntu-server-jammy:22_04-lts-gen2:latest')
1213+
vms = self.cmd('vm list -g {rg} -o json').get_output_in_json()
1214+
# Something wrong with vm create command if it fails here
1215+
assert len(vms) == 1
1216+
1217+
# Create Repair VM
1218+
repair_vm = self.cmd('vm repair create -g {rg} -n {vm} --repair-username {admin_username} --repair-password {admin_password} --yes -o json').get_output_in_json()
1219+
assert repair_vm['status'] == STATUS_SUCCESS, repair_vm['error_message']
1220+
# Check repair VM
1221+
self.kwargs.update({
1222+
'vm': 'vm1',
1223+
'admin_password': secure_password,
1224+
'admin_username': secure_username,
1225+
'repair_resource_group': repair_vm['repair_resource_group']
1226+
})
1227+
repair_vms = self.cmd('vm list -g {repair_resource_group} -o json').get_output_in_json()
1228+
assert len(repair_vms) == 1
1229+
repair_vm = repair_vms[0]
1230+
# Verify the image sku is the expected sku from source vm.
1231+
image_info = repair_vm['storageProfile']['imageReference']
1232+
assert image_info['sku'] == "22_04-lts-gen2"
1233+
1234+
self.kwargs.update({
1235+
'vm': 'vm1',
1236+
'admin_password': secure_password,
1237+
'admin_username': secure_username
1238+
})
1239+
# Run a script using long parameter parsing
1240+
result_run = self.cmd('vm repair run -g {rg} -n {vm} --run-on-repair --run-id linux-alar2 --parameters test ++initiator=SELFHELP -o json').get_output_in_json()
1241+
assert result_run['status'] == STATUS_SUCCESS, result_run['error_message']
1242+
log_contains_initiator_selfhelp = "initiator=selfhelp" in result_run['logs'].lower()
1243+
assert log_contains_initiator_selfhelp, "The logs do not contain 'initiator=selfhelp'"
1244+
1245+
# Call Restore
1246+
self.cmd('vm repair restore -g {rg} -n {vm} --yes')

src/vm-repair/setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from codecs import open
99
from setuptools import setup, find_packages
1010

11-
VERSION = "2.0.2"
11+
VERSION = "2.0.3"
1212

1313
CLASSIFIERS = [
1414
'Development Status :: 4 - Beta',

0 commit comments

Comments
 (0)