lib/sles4sap/aws_cli.pm

SYNOPSIS

Library to compose and run AWS cli commands.

_aws_tag_specifications

my @args = _aws_tag_specifications('vpc', { openqa_var_job_id => '123', openqa_created_date => '2026-01-01T00:00:00' });

Private function. Convert a hashref of tags into a --tag-specifications argument pair for EC2 create commands. The resource_type is mandatory: "When you specify a tag, you must specify the resource type to tag, otherwise the request will fail." (AWS CLI reference). It must match the primary resource created by the command (e.g. 'vpc' for create-vpc). Keys are sorted for deterministic output. Return an empty list if the hashref is empty or undef.

Croak if any tag violates AWS tag restrictions: - Empty key - Undefined value - Key longer than 128 characters - Value longer than 256 characters - Key starting with the reserved prefix aws: - More than 50 tags

Croak also if a key or value contains characters outside the set [A-Za-z0-9+\-=_:.\/@]. This set is stricter than the AWS limits, because AWS also accepts spaces and Unicode letters. The tag list is inside double quotes in a shell command and uses the AWS CLI shorthand syntax. Characters such as $, backtick, space, ,, { or } can break the command or cause shell expansion. Do not add them to the set.

aws_vpc_create

my $vpc_id = aws_vpc_create(
    region => 'us-west',
    cidr => '1.2.3/18',
    tags => { openqa_var_job_id => '123' });

Create a new AWS VPC with a specified CIDR block. If tags is given, those tags are applied to the VPC. Returns the VPC ID.

region - AWS region where to create the VPC
cidr - CIDR block for the VPC (e.g., '10.0.0.0/16')
tags - hashref of tags to apply (optional)

aws_vpc_get_id

my $vpc_id = aws_vpc_get_id(
    region => 'us-west',
    job_id => 'abc123456');

Retrieve the VPC ID associated with a specific OpenQA job Returns the VPC ID

region - AWS region where the VPC is located
job_id - OpenQA job identifier used to tag the VPC

aws_vpc_delete

my $ret = aws_vpc_delete(
    region => 'us-west',
    vpc_id => 'vpc-456');

Delete the VPC, do not assert but return the exit code of the command.

region - AWS region where the VPC is located
vpc_id - ID of the VPC to delete

aws_security_group_create

my $sg_id = aws_security_group_create(
    region => 'uswest',
    group_name => 'something',
    description => 'be or not to be',
    vpc_id => 'vpc123456',
    tags => { openqa_var_job_id => '123' });

Create an AWS security group within a VPC. If tags is given, those tags are applied to the security group. Returns the security group ID.

region - AWS region where to create the security group
group_name - name for the security group
description - description of the security group purpose
vpc_id - ID of the VPC where the security group will be created
tags - hashref of tags to apply (optional)

aws_security_group_delete

my $ret = aws_security_group_delete(
    region => 'uswest',
    group_name => 'something',
    description => 'be or not to be',
    vpc_id => 'vpc123456',
    job_is => '7890');

Delete the security group, do not assert but return the exit code of the command.

region - AWS region where to create the security group
job_id - OpenQA job identifier used to tag the VPC

aws_security_group_get_id

my $sg_id = aws_security_group_get_id(region => 'europe', job_id => '12345');

Retrieve the security group ID associated with a specific OpenQA job Returns the security group ID

region - AWS region where the security group is located
job_id - OpenQA job identifier used to tag the security group

aws_security_group_authorize_ingress

aws_security_group_authorize_ingress(
    sg_id => ,
    protocol => ,
    port =>,
    cidr =>,
    region => );

Add an ingress rule to a security group allowing traffic from a specific CIDR block

sg_id - ID of the security group to modify
protocol - protocol for the rule (e.g., 'tcp', 'udp', 'icmp')
port - port number or port range for the rule
cidr - CIDR block allowed to access (e.g., '0.0.0.0/0' for all)
region - AWS region where the security group is located

aws_subnet_create

my $subnet_id = aws_subnet_create(
    region => 'us-west-1',
    cidr => '10.0.1.0/24',
    vpc_id => 'vpc-12345',
    tags => { openqa_var_job_id => '123' }
);

Create a subnet within a VPC with a specified CIDR block. If tags is given, those tags are applied to the subnet. Returns the subnet ID.

region - AWS region where to create the subnet
cidr - CIDR block for the subnet (e.g., '10.0.1.0/24')
vpc_id - ID of the VPC where the subnet will be created
tags - hashref of tags to apply (optional)

aws_subnet_get_ids

my @subnet_ids = aws_subnet_get_ids(
    region => 'us-west-1',
    job_id => '67890'
);

Retrieve the list of subnet IDs associated with a specific OpenQA job Returns the list of subnet IDs

region - AWS region where the subnets are located
job_id - OpenQA job identifier used to tag the subnets

aws_subnet_delete

my $ret = aws_subnet_delete(
    region => 'us-west-1',
    job_id => '67890'
);

Delete the subnets associated with the job, do not assert but return the exit code of the command.

region - AWS region where the subnets are located
job_id - OpenQA job identifier used to tag the subnets

aws_internet_gateway_create

my $igw_id = aws_internet_gateway_create
    region => 'us-west-1',
    tags => { openqa_var_job_id => '123' }
);

Create an internet gateway. If tags is given, those tags are applied to the internet gateway. Returns the internet gateway ID.

region - AWS region where to create the internet gateway
tags - hashref of tags to apply (optional)

aws_internet_gateway_get_id

my $igw_id = aws_internet_gateway_get_id(
    region => 'us-west-1',
    job_id => '67890'
);

Retrieve the internet gateway ID associated with a specific OpenQA job Returns the internet gateway ID

region - AWS region where the internet gateway is located
job_id - OpenQA job identifier used to tag the internet gateway

aws_internet_gateway_attach

aws_internet_gateway_attach(
    vpc_id => 'vpc-12345',
    igw_id => 'igw-abcde',
    region => 'us-west-1'
);

Attach an internet gateway to a VPC

vpc_id - ID of the VPC to attach the gateway to
igw_id - ID of the internet gateway to attach
region - AWS region where the resources are located

aws_internet_gateway_delete

my $ret = aws_internet_gateway_delete(
    job_id => '6789',
    vpc_id => 'vpc-12345',
    region => 'us-west-1'
);

Delete the internet gateway, do not assert but return the exit code of the command.

region - AWS region where the resources are located
vpc_id - ID of the VPC to attach the gateway to
job_id - OpenQA job identifier for tagging

aws_route_table_create

my $route_table_id = aws_route_table_create(
    region => 'us-west-1',
    vpc_id => 'vpc-12345'
);

Create a route table within a VPC Returns the route table ID

region - AWS region where to create the route table
vpc_id - ID of the VPC where the route table will be created

aws_route_table_associate

aws_route_table_associate(
    subnet_id => 'subnet-12345',
    route_table_id => 'rtb-abcde',
    region => 'us-west-1'
);

Associate a route table with a subnet

subnet_id - ID of the subnet to associate
route_table_id - ID of the route table to associate
region - AWS region where the resources are located

aws_route_table_delete

my $ret = aws_route_table_delete(
    vpc_id => 'subnet-12345',
    region => 'us-west-1'
);

Delete the route table(s), do not assert but return the first non-zero exit code of the commands, or 0 on success.

vpc_id - ID of the VPC
region - AWS region where the resources are located

aws_route_create

aws_route_create(
    route_table_id => 'rtb-12345',
    destination_cidr_block => '0.0.0.0/0',
    igw_id => 'igw-abcde',
    region => 'us-west-1'
);

Create a route in a route table pointing to an internet gateway

route_table_id - ID of the route table where to create the route
destination_cidr_block - destination CIDR block for the route (e.g., '0.0.0.0/0' for default route)
igw_id - ID of the internet gateway as the route target
region - AWS region where the resources are located

aws_vm_create

my $instance_id = aws_vm_create(
    instance_type => 't2.micro',
    image_name    => 'sles-15-sp3',
    subnet_id     => 'subnet-12345',
    sg_id         => 'sg-abcde',
    ssh_key       => 'my-key',
    region        => 'us-west-1',
    tags          => { openqa_var_job_id => '123' }
);

Launch an EC2 instance with specified configuration. If tags is given, those tags are applied to the instance. Returns the instance ID.

instance_type - EC2 instance type (e.g., 't2.micro', 'm5.large')
image_name - Name to use for the instance
owner - Image owner, used to serch the AMI
subnet_id - ID of the subnet where to launch the instance
sg_id - ID of the security group to assign to the instance
ssh_key - name of the SSH key pair for instance access
region - AWS region where to launch the instance
tags - hashref of tags to apply (optional)

_aws_ec2_describe_instances

my $data = _aws_ec2_describe_instances(
    region => 'us-west-1',
    filters => "'Name=instance-id,Values=i-12345'",
    query => 'Reservations[0].Instances[0].State.Name');

Internal function. Run aws ec2 describe-instances with JSON output. The timeout command stops aws before the script_output timeout. The function uses proceed_on_failure. Return the decoded JSON data structure. Return undef if the output is empty. Die if the output is not valid JSON.

region - AWS region
filters - value for --filters, already quoted for the shell
query - JMESPath query, without quotes

aws_vm_get_id

my @instance_ids = aws_vm_get_id(
    region => 'us-west-1',
    job_id => '67890'
);

Retrieve the IDs of the EC2 instances associated with a specific OpenQA job. Terminated and shutting-down instances are ignored. Return a list of instance IDs. The list is empty if no instance is found or if the aws command fails. The caller must check how many elements the list has.

region - AWS region where the instance is located
job_id - OpenQA job identifier used to tag the instance

aws_vm_get_diagnostics

my $diag = aws_vm_get_diagnostics(
    region => 'us-west-2',
    instance_id => 'i-09dadefca25944818'
);

Return a hash reference with diagnostic data about the instance: id, state, state_transition, state_reason, public_ip, private_ip, launch_time. Return undef if the instance is not found or if the aws command fails. Never dies at runtime.

region - AWS region where the instance is located
instance_id - ID of the instance

aws_vm_describe_status

my $out = aws_vm_describe_status(
    region => 'us-west-2',
    instance_id => 'i-09dadefca25944818'
);

Return the output of describe-instance-status: instance state and
system/instance status checks, also for not running instances.
Never dies: the aws command is killed by C<timeout> before the
script_output timeout, and a failure or a kill returns the command
output (proceed_on_failure).
region - AWS region where the instance is located
instance_id - ID of the instance

aws_vm_wait_status_ok

die 'VM not running' if aws_vm_wait_status_ok(
    region => 'us-west-1',
    instance_id => 'i-12345'
);

Wait for an EC2 instance to reach the 'running' state. A failed aws command counts as "not running yet". Return 0 if the instance reaches 'running' in time. Die with the last known state if it does not.

region - AWS region where the instance is located
instance_id - ID of the instance to monitor
timeout - maximum time to wait in seconds (default 600)
delay - time between two checks in seconds (default 15)

aws_pubip_get

my $ip = aws_pubip_get(
    region => 'us-west-1',
    instance_id => 'i-12345'
);

Retrieve the public IP address of an EC2 instance. Return the public IP address, or undef if the instance has no public IP, is not found, or if the aws command fails.

region - AWS region where the instance is located
instance_id - ID of the instance

aws_vm_terminate

my $ret = aws_vm_terminate(
    region => 'us-west-1',
    instance_id => 'i-12345'
);

Terminate an EC2 instance and wait for it to be terminated, do not assert but return the exit code of the command.

region - AWS region where the instance is located
instance_id - ID of the instance to terminate

aws_ssh_key_pair_import

aws_ssh_key_pair_import(
    ssh_key      => 'my-key',
    pub_key_path => '/path/to/key.pub'
);

Import an SSH public key pair into AWS EC2 for instance authentication

ssh_key - name to assign to the imported key pair in AWS
pub_key_path - filesystem path to the public key file

aws_tgw_vpc_attachment_get_id

my $attach_id = aws_tgw_vpc_attachment_get_id(region => 'us-west-1', job_id => 'job-123');

Retrieve the TGW attachment ID associated with a specific OpenQA job. Returns the TGW attachment ID as a string. Only the first element found is returned.

aws_filter_query

my $res = aws_filter_query(cmd => 'describe-instances', filter => 'Name=instance-id,Values=i-123', query => 'Reservations[*].Instances[*].InstanceId');

Generic function to compose a aws cli command with filter and query. Returns the script output.

cmd - AWS EC2 subcommand
filter - Filter string
query - JMESPath query string
output - Output format (default: text)

aws_tgw_get_id

my $tgw_id = aws_tgw_get_id(mirror_tag => 'my-project');

Return the Transit Gateway ID associated with a specific Project tag.

mirror_tag - Value of Project tag
region - Region

aws_vpc_get_subnets

my @subnets = aws_vpc_get_subnets(vpc_id => 'vpc-123', region => 'us-east-1');

Return a list of subnets for a VPC, one per Availability Zone.

vpc_id - VPC ID
region - AWS region

aws_vpc_get_routing_tables

my $rt_ids = aws_vpc_get_routing_tables(vpc_id => 'vpc-123', region => 'us-east-1');

Get routing table IDs for a VPC that have external connections (non-local).

vpc_id - VPC ID
region - AWS region

aws_tgw_attachment_get

my $res = aws_tgw_attachment_get(name => 'my-attachment');

Get a description of one or more transit-gateway-attachments. Returns an array reference of hash references (list of dicts). return value = [ {State => 'pending'} ...]

transit_gateway_attach_id - Optional ID of the attachment
name - Optional Name tag value

aws_tgw_attachment_create

aws_tgw_attachment_create(
    transit_gateway_id => 'tgw-123',
    vpc_id => 'vpc-456',
    subnet_id_list => ['subnet-1'],
    name => 'my-attach'
);

Create a Transit Gateway VPC attachment and wait until it is available. Returns true if the attachment becomes available within the timeout, false otherwise.

transit_gateway_id - ID of the target Transit gateway
vpc_id - VPC ID to be attached
subnet_id_list - List of subnet IDs to connect
name - Prefix for the Tag Name of the attachment
timeout - Timeout in seconds (default 300)

aws_tgw_attachment_delete

aws_tgw_attachment_delete(id => 'tgwa-123');

Delete a Transit Gateway VPC attachment and wait until it is deleted. Returns true if the attachment is successfully deleted (or if wait is set to 0), false if it times out while waiting for the deleted state.

id - ID of the TGW attachment to be deleted
timeout - Timeout in seconds (default 300)
wait - whether to wait to verify deleted status or not (default 1)

aws_route_create_tgw

aws_route_create_tgw(rtable_id => 'rtb-1', target_ip_net => '10.0.0.0/8', trans_gw_id => 'tgw-1');

Add a route to a Transit Gateway in a routing table.

rtable_id - Routing table ID
target_ip_net - Target CIDR block
trans_gw_id - Transit Gateway ID