1

The function below as well as others that I have in the script to collect a complete inventory of everything we have in AWS, runs without any problems.

However, I am missing all of the IP addresses that are assigned to the instance after the first one when the instance has more than one interface.

How can I make sure to get all the ip addresses of every instance in the function below before writing the details into the excel worksheet?

function Create-EC2InstanceWorksheet {

 #Creating EC2 Instances Worksheet

        # Add Excel worksheet
        $workbook.Worksheets.Add()

        # We need to create a sheet for the Instances
        $InstancesWorksheet = $workbook.Worksheets.Item(1)
        $InstancesWorksheet.Name = 'Instances'

        # Headers for the Instance worksheet
        $InstancesWorksheet.Cells.Item(1,1) = 'Region'
        $InstancesWorksheet.Cells.Item(1,2) = 'Instance Name'
        $InstancesWorksheet.Cells.Item(1,3) = 'Image ID'
        $InstancesWorksheet.Cells.Item(1,4) = 'Instance ID'
        $InstancesWorksheet.Cells.Item(1,5) = 'PEM File'
        $InstancesWorksheet.Cells.Item(1,6) = 'Instance Type'
        $InstancesWorksheet.Cells.Item(1,7) = 'Private IP'
        $InstancesWorksheet.Cells.Item(1,8) = 'Public IP'
        $InstancesWorksheet.Cells.Item(1,9) = 'VPC ID'
        $InstancesWorksheet.Cells.Item(1,10) = 'Subnet ID'
        $InstancesWorksheet.Cells.Item(1,11) = 'State'
        $InstancesWorksheet.Cells.Item(1,12) = 'Security Group Id'
        $InstancesWorksheet.Cells.Item(1,13) = 'Source/Dest Check'

        # Excel Cell Counter
        $row_counter = 3
        $column_counter = 1



    # Get the Ec2 instances for each region
    foreach($AWS_Locations_Iterator in $AWS_Locations){
        $EC2Instances = Get-EC2Instance -Region $AWS_Locations_Iterator

        # Iterating over each instance

foreach($EC2Instances_Iterator.Instances.NetworkInterfaces.PrivateIpAddresses.PrivateIpAddress in $EC2Instances){

foreach($EC2Instances_Iterator.Instances.NetworkInterfaces.Pr ... + ~ Missing 'in' after variable in foreach loop.

Remove the code above starting at foreach and used the suggestion provided by @AnthonyNeace. Replaced with the foreach below which does provide the additional ip addresses.

        foreach($instance in $EC2Instances.Instances){
            foreach($networkInterface in $instance.NetworkInterfaces){
            "$($instance.InstanceID): $($networkInterface.PrivateIpAddresses.PrivateIpAddress)";



            # Ignore if a region does not have any instances
            if($EC2Instances_Iterator.count -eq $null) {
            continue
            }
            # Populating the cells
            $InstancesWorksheet.Cells.Item($row_counter,$column_counter++) = $AWS_Locations_Iterator
            $InstancesWorksheet.Cells.Item($row_counter,$column_counter++) = $EC2Instances_Iterator.Instances.Tags.value
            $InstancesWorksheet.Cells.Item($row_counter,$column_counter++) = $EC2Instances_Iterator.Instances.imageid
            $InstancesWorksheet.Cells.Item($row_counter,$column_counter++) = $EC2Instances_Iterator.Instances.Instanceid
            $InstancesWorksheet.Cells.Item($row_counter,$column_counter++) = $EC2Instances_Iterator.Instances.keyname.tostring()
            $InstancesWorksheet.Cells.Item($row_counter,$column_counter++) = $EC2Instances_Iterator.Instances.Instancetype.Value
            $InstancesWorksheet.Cells.Item($row_counter,$column_counter++) = $EC2Instances_Iterator.Instances.PrivateIpAddress
            $InstancesWorksheet.Cells.Item($row_counter,$column_counter++) = $EC2Instances_Iterator.Instances.PublicIpAddress
            $InstancesWorksheet.Cells.Item($row_counter,$column_counter++) = $EC2Instances_Iterator.Instances.VpcId
            $InstancesWorksheet.Cells.Item($row_counter,$column_counter++) = $EC2Instances_Iterator.Instances.SubnetId
            $InstancesWorksheet.Cells.Item($row_counter,$column_counter++) = $EC2Instances_Iterator.Instances.state.name.value
            $InstancesWorksheet.Cells.Item($row_counter,$column_counter++) = $EC2Instances_Iterator.Instances.securitygroups.GroupId
            $InstancesWorksheet.Cells.Item($row_counter,$column_counter++) = $EC2Instances_Iterator.Instances.SourceDestCheck


            # Seting the row and column counter for next EC2 instance entry
            $row_counter = $row_counter + 1
            $column_counter = 1
        }

        # Iterating to the next region
        $row_counter = $row_counter + 1
    }

}

1 Answers1

0

The network interface is included with each EC2 Instance in the Get-EC2Instance response, so taking the private ip addresses as an example... you could access the private IP addresses by simply iterating over each private ip address exposed on each network interface. Same for the IPv6 addresses.

Object Model

IPv4 Example

$EC2Instances_Iterator.Instances.NetworkInterfaces.PrivateIpAddresses.PrivateIpAddress

IPv6 Example

$EC2Instances_Iterator.Instances.NetworkInterfaces.Ipv6Addresses.Ipv6Address

Example: Write addresses string using foreach loop

This example builds the addresses across each network interface into a comma-delimited string within the scope of the instances loop. So a string is created for each instance.

The powershell subexpression operator $() is used to resolve complex properties in the string.

$EC2Instances = Get-EC2Instance

foreach($instance in $EC2Instances.Instances){
  $addresses = "";
  foreach($networkInterface in $instance.NetworkInterfaces){
    $addresses = $addresses, $networkInterface.PrivateIpAddresses.PrivateIpAddress -join ","
  }
  "$($instance.InstanceID): $($addresses.Trim(','))"    
}

Further Reading

Anthony Neace
  • 25,013
  • 7
  • 114
  • 129
  • I attempted to add the "$EC2Instances_Iterator.Instances.NetworkInterfaces.PrivateIpAddresses.PrivateIpAddress" to my script right were I am doing the foreach, but it does not like my syntax and complains that I am missing the "in". Get the Ec2 instances for each region foreach($AWS_Locations_Iterator in $AWS_Locations){ $EC2Instances = Get-EC2Instance -Region $AWS_Locations_Iterator # Iterating over each instance foreach($EC2Instances_Iterator in $EC2Instances){ – Robert Booth Apr 19 '17 at 16:06
  • @RobertBooth Can you append to your question with your revised attempt and any related errors? Comments don't format code snippets very well. – Anthony Neace Apr 19 '17 at 16:08
  • Also, if it helps, you can treat this value in `privateipaddresses.privateipaddress` much in the same way that you're treating the `Tags.Value` collection. You can populate a new cell with the result. – Anthony Neace Apr 19 '17 at 16:12
  • I added the details and my script did not like the line. Going to append details to my post as you suggested. – Robert Booth Apr 19 '17 at 16:13
  • I will try the "privateipaddresses.privateipaddress" and let you know right away. I appreciate your assistance! @Anthony Neace – Robert Booth Apr 19 '17 at 16:23
  • @RobertBooth Updated my answer with a simple example to iterate through instances and output a string with these values. – Anthony Neace Apr 19 '17 at 16:33
  • When I add that to the script to treat as I am with tags, I get no data in the variable. I can't even seem to find a way to run the Get-ec2instance command straight at the powershell prompt and have it return all ip addresses for the instance. I can only get one of the IPs @AnthonyNeace – Robert Booth Apr 19 '17 at 16:51
  • @RobertBooth To troubleshoot from the command line, try something like this: `@(Get-EC2Instance) | % {$_.Instances} | % { $_.NetworkInterfaces }` You can do a sanity check from there to see if you do have multiple addresses per instance. – Anthony Neace Apr 19 '17 at 16:56
  • I took the syntax you provided - example of the loop that uses the subexpression operator. My script does get the additional IP addresses but am having a hard time writing each diff ip to excel on same line. At present, whenever there are two interface/ipadd, I have two lines for the same instance. Variable seems to get over written when I try sliding in my write to excel in between the loops to get the two ip addresses. @AnthonyNeace – Robert Booth Apr 19 '17 at 19:12
  • @RobertBooth Gotcha; you can do this by building the addresses across each network interface for an instance within the scope of the foreach EC2Instance loop, rather than the foreach NetworkInterface loop. I've updated my answer with an example that will do this for a simple string. – Anthony Neace Apr 19 '17 at 20:19