Skip to content

Commit

Permalink
Add more az cli wrappers for VM (os-autoinst#19402)
Browse files Browse the repository at this point in the history
Add more functions to manage VM.
  • Loading branch information
mpagot authored May 28, 2024
1 parent e2af63c commit d0db1a3
Show file tree
Hide file tree
Showing 3 changed files with 165 additions and 11 deletions.
86 changes: 78 additions & 8 deletions lib/sles4sap/azure_cli.pm
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,10 @@ our @EXPORT = qw(
az_network_lb_rule_create
az_vm_as_create
az_vm_create
az_vm_name_get
az_vm_openport
az_vm_wait_cloudinit
az_vm_instance_view_get
az_nic_id_get
az_nic_name_get
az_ipconfig_name_get
Expand Down Expand Up @@ -81,11 +83,9 @@ sub az_group_create {
assert_script_run($az_cmd);
}



=head2 az_group_name_get
az_group_name_get();
my $ret = az_group_name_get();
Get the name of all existing Resource groups in the current subscription
Expand Down Expand Up @@ -134,6 +134,11 @@ sub az_network_vnet_create {
croak("Argument < $_ > missing") unless $args{$_}; }
$args{address_prefixes} //= '192.168.0.0/16';
$args{subnet_prefixes} //= '192.168.0.0/24';
foreach (qw(address_prefixes subnet_prefixes)) {
croak "Invalid IP range $args{$_} in $_"
unless ($args{$_} =~ /^[1-9]{1}[0-9]{0,2}\.(0|[1-9]{1,3})\.(0|[1-9]{1,3})\.(0|[1-9]{1,3})\/[0-9]+$/);
}

my $az_cmd = join(' ', 'az network vnet create',
'--resource-group', $args{resource_group},
'--location', $args{region},
Expand Down Expand Up @@ -295,7 +300,7 @@ sub az_network_publicip_get {
vnet => 'openqa-vnet',
snet => 'openqa-subnet',
backend => 'openqa-be',
frontend_ip => 'openqa-feip',
frontend_ip_name => 'openqa-feip',
sku => 'Standard')
Create a load balancer entity.
Expand All @@ -316,7 +321,7 @@ SKU Standard (and not Basic) is needed to get some Metrics
=item B<backend> - name to assign to created backend pool
=item B<frontend_ip> - name to assign to created frontend ip, will be reused in "az network lb rule create"
=item B<frontend_ip_name> - name to assign to created frontend ip, will be reused in "az network lb rule create"
=item B<sku> - default Basic
Expand All @@ -327,11 +332,16 @@ SKU Standard (and not Basic) is needed to get some Metrics

sub az_network_lb_create {
my (%args) = @_;
foreach (qw(resource_group name vnet snet backend frontend_ip)) {
foreach (qw(resource_group name vnet snet backend frontend_ip_name)) {
croak("Argument < $_ > missing") unless $args{$_}; }

$args{sku} //= 'Basic';
my $fip_cmd = $args{fip} ? "--private-ip-address $args{fip}" : '';
my $fip_cmd = '';
if ($args{fip}) {
croak "Invalid IP address fip:$args{fip}"
unless ($args{fip} =~ /^[1-9]{1}[0-9]{0,2}\.(0|[1-9]{1,3})\.(0|[1-9]{1,3})\.[1-9]{1}[0-9]{0,2}$/);
$fip_cmd = "--private-ip-address $args{fip}";
}

my $az_cmd = join(' ', 'az network lb create',
'--resource-group', $args{resource_group},
Expand All @@ -340,7 +350,7 @@ sub az_network_lb_create {
'--vnet-name', $args{vnet},
'--subnet', $args{snet},
'--backend-pool-name', $args{backend},
'--frontend-ip-name', $args{frontend_ip},
'--frontend-ip-name', $args{frontend_ip_name},
$fip_cmd);
assert_script_run($az_cmd);
}
Expand Down Expand Up @@ -555,6 +565,66 @@ sub az_vm_create {
assert_script_run($az_cmd, timeout => 600);
}

=head2 az_vm_name_get
my $ret = az_vm_name_get(resource_group => 'openqa-rg');
Get the name of all existing VMs within a Resource groups
=over 1
=item B<resource_group> - existing resource group where to create the network
=back
=cut

sub az_vm_name_get {
my (%args) = @_;
croak("Argument < resource_group > missing") unless $args{resource_group};
my $az_cmd = join(' ',
'az vm list',
"-g $args{resource_group}",
'--query "[].name"',
'-o json');
return decode_json(script_output($az_cmd));
}

=head2 az_vm_instance_view_get
my $res = az_vm_instance_view_get(
resource_group => 'openqa-rg',
name => 'openqa-vm')
Get some details of a specific VM
Json output looks like:
[
"PowerState/running",
"VM running"
]
=over 2
=item B<resource_group> - existing resource group where to create the VM
=item B<name> - name of an existing virtual machine
=back
=cut

sub az_vm_instance_view_get {
my (%args) = @_;
foreach (qw(resource_group name)) {
croak("Argument < $_ > missing") unless $args{$_}; }
my $az_cmd = join(' ',
'az vm get-instance-view',
'--name', $args{name},
'--resource-group', $args{resource_group},
'--query "instanceView.statuses[1].[code,displayStatus]"');
return decode_json(script_output($az_cmd));
}

=head2 az_vm_openport
az_vm_openport(
Expand Down
2 changes: 1 addition & 1 deletion lib/sles4sap/ipaddr2.pm
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ sub ipaddr2_azure_deployment {
vnet => $vnet,
snet => $subnet,
backend => $lb_be,
frontend_ip => $lb_fe,
frontend_ip_name => $lb_fe,
fip => $lb_feip,
sku => 'Standard');

Expand Down
88 changes: 86 additions & 2 deletions t/21_sles4sap_azure_cli.t
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ subtest '[az_group_create] missing args' => sub {
dies_ok { az_group_create(name => 'Arlecchino') } 'Die for missing argument region';
};


subtest '[az_group_name_get]' => sub {
my $azcli = Test::MockModule->new('sles4sap::azure_cli', no_auto => 1);
my @calls;
Expand All @@ -51,6 +50,34 @@ subtest '[az_network_vnet_create]' => sub {
ok((any { /az network vnet create/ } @calls), 'Correct composition of the main command');
};

subtest '[az_network_vnet_create] die on invalid IP' => sub {
my $azcli = Test::MockModule->new('sles4sap::azure_cli', no_auto => 1);
my @calls;
$azcli->redefine(assert_script_run => sub { push @calls, $_[0]; return; });

foreach my $arg (qw(address_prefixes subnet_prefixes)) {
foreach my $test_pattern (qw(192.168.0/16 192.168..0/16 192.068.0.0/16 192.168.0.0 192.168.000.000/16 1192.168.0.0/16)) {
dies_ok { az_network_vnet_create(
resource_group => 'Arlecchino',
region => 'Pulcinella',
vnet => 'Pantalone',
snet => 'Colombina',
$arg => $test_pattern) } "Die for invalid IP $test_pattern as argument $arg";
ok scalar @calls == 0, "No call to assert_script_run, croak before to run the command for invalid IP $test_pattern as argument $arg";
@calls = ();
}
foreach my $test_pattern (qw(192.168.0.0/16 192.0.0.0/16 2.168.0.0/16)) {
az_network_vnet_create(
resource_group => 'Arlecchino',
region => 'Pulcinella',
vnet => 'Pantalone',
snet => 'Colombina',
$arg => $test_pattern);
ok scalar @calls > 0, "Some calls to assert_script_run for valid IP $test_pattern as argument $arg";
@calls = ();
}
}
};

subtest '[az_network_nsg_create]' => sub {
my $azcli = Test::MockModule->new('sles4sap::azure_cli', no_auto => 1);
Expand Down Expand Up @@ -126,11 +153,43 @@ subtest '[az_network_lb_create]' => sub {
vnet => 'Pantalone',
snet => 'Colombina',
backend => 'Smeraldina',
frontend_ip => 'Momolo');
frontend_ip_name => 'Momolo');
note("\n --> " . join("\n --> ", @calls));
ok((any { /az network lb create/ } @calls), 'Correct composition of the main command');
};

subtest '[az_network_lb_create] with a fixed IP' => sub {
my $azcli = Test::MockModule->new('sles4sap::azure_cli', no_auto => 1);
my @calls;
$azcli->redefine(assert_script_run => sub { push @calls, $_[0]; return; });
az_network_lb_create(
resource_group => 'Arlecchino',
name => 'Truffaldino',
vnet => 'Pantalone',
snet => 'Colombina',
backend => 'Smeraldina',
frontend_ip_name => 'Momolo',
fip => '1.2.3.4');
note("\n --> " . join("\n --> ", @calls));
ok((any { /az network lb create/ } @calls), 'Correct composition of the main command');
};

subtest '[az_network_lb_create] with an invalid fixed IP' => sub {
my $azcli = Test::MockModule->new('sles4sap::azure_cli', no_auto => 1);
my @calls;
$azcli->redefine(assert_script_run => sub { push @calls, $_[0]; return; });

dies_ok { az_network_lb_create(
resource_group => 'Arlecchino',
name => 'Truffaldino',
vnet => 'Pantalone',
snet => 'Colombina',
backend => 'Smeraldina',
frontend_ip_name => 'Momolo',
fip => '1.2.3.') } "Die for invalid IP as fip argument";
ok scalar @calls == 0, "No call to assert_script_run if IP is invalid";
};

subtest '[az_vm_as_create]' => sub {
my $azcli = Test::MockModule->new('sles4sap::azure_cli', no_auto => 1);
my @calls;
Expand Down Expand Up @@ -181,6 +240,31 @@ subtest '[az_vm_create] with no public IP' => sub {
ok((any { /--public-ip-address ""/ } @calls), 'empty Public IP address');
};

subtest '[az_vm_name_get]' => sub {
my $azcli = Test::MockModule->new('sles4sap::azure_cli', no_auto => 1);
my @calls;
$azcli->redefine(script_output => sub { push @calls, $_[0]; return '["Mirandolina","Truffaldino"]'; });

my $res = az_vm_name_get(resource_group => 'Arlecchino');

note("\n --> " . join("\n --> ", @calls));
ok((any { /az vm list/ } @calls), 'Correct composition of the main command');
ok((any { /-g Arlecchino/ } @calls), 'Correct composition of the -g argument');
ok((any { /Mirandolina/ } @$res), 'Correct result decoding');
};

subtest '[az_vm_instance_view_get]' => sub {
my $azcli = Test::MockModule->new('sles4sap::azure_cli', no_auto => 1);
my @calls;
$azcli->redefine(script_output => sub { push @calls, $_[0]; return '["PowerState/running","VM running"]'; });

my $res = az_vm_instance_view_get(resource_group => 'Arlecchino', name => 'Mirandolina');

note("\n --> " . join("\n --> ", @calls));
ok((any { /az vm get-instance-view/ } @calls), 'Correct composition of the main command');
ok((any { /VM running/ } @$res), 'Correct result decoding');
};

subtest '[az_vm_openport]' => sub {
my $azcli = Test::MockModule->new('sles4sap::azure_cli', no_auto => 1);
my @calls;
Expand Down

0 comments on commit d0db1a3

Please sign in to comment.