0

I have an EC2 Instance running an old AMI from AWS, which in my current setup is from WINDOWS_2016_BASE. Now I know that, but the Instance doesn't know that.

Using PowerShell I want the EC2 Instance to create more like itself, but not from an AMI I have created (as that would of course always be at the old version) and not "directly" from the actual AMI ImageId it was created from. As AWS don't allow that if it is not the latest version of it (hence I need the indirect route to getting that AMI ImageId, even if it turns out to to be the same.. i.e if it the latest version already).

So I need to find, using PowerShell, the latest version of an AMI I already know (which I got from the metadata) and I do not want to specify the name of the AMI e.g WINDOWS_2016_BASE since I would like the machine to create more like itself without me having to hardcode what it is in the script.

I have no idea how to do this since using Get-EC2ImageByName -Names WINDOWS_2016_BASE is not what I want to do since I don't want to hardcode that names parameter or pass it in through userdata.

Get-EC2Image -ImageId <an old imageid> returns null since the AMI is no longer current.

henrycarteruk
  • 12,708
  • 2
  • 36
  • 40
cineam mispelt
  • 393
  • 1
  • 8
  • Unfortunately, once the AMI has been deprecated it is not possible to retrieve the Name of the AMI. Therefore, you would need to provide the name for the search. – John Rotenstein Apr 21 '17 at 04:27

2 Answers2

2

This will be somewhat difficult without either stashing this name somewhere that your script can cue off of (which you've stated that you don't want to do), or relying on some mapping between names/amis (that Get-EC2ImageByName already does for you).

AMI metadata is designed such that it is easy to retrieve a 'family tree' of related AMIs, under the assumption that their names are similar excepting for maybe minor differences such as versions or dates. It is a common pattern that prefixes of related AMIs will be consistent, which makes them easier to search for and aggregate.

This point makes your approach difficult, because your scripts will be missing that bit of data -- the AMI name prefix.

You could dynamically retrieve your instance's AMI ID from the metadata service and pass that into Get-EC2Image to get AMI details, but you couldn't go further from there without some sort of name prefix to match against and use to search for related AMIs that are newer.

Maybe reconsider this approach, and keep the name prefix stashed in a tag or on the instance via user-data? For example, I just checked and the English Windows Server 2016 Base AMIs all share this prefix: Windows_Server-2016-English-Full-Base. If you stored that on your instance or as one of your tags, your script could retrieve it and run the following powershell to get the latest Windows Server 2016 AMI:

@(Get-EC2Image -Owner amazon -Filter @{ Name="name"; Values="Windows_Server-2016-English-Full-Base*" } | Sort CreationDate -Desc)[0].ImageId
Anthony Neace
  • 25,013
  • 7
  • 114
  • 129
  • CLI equivalent: `aws ec2 describe-images --query Images[*].[ImageId,Name] --filters Name=name,Values=Windows_Server-2016-English-Full-Base-*`, then sort the result. – John Rotenstein Apr 21 '17 at 04:26
  • Thanks, it's a good answer, but it's kind of at the same point where the question left off, in that precisely what i don't want to do becomes the answer ;-) I beleive i have found the answer somewhat which i will post now. – cineam mispelt Apr 21 '17 at 04:50
  • @cineammispelt Right, I suppose the impetus for this is that I'm challenging the premise of your question, and prompting you to consider why this solution -- which is more or less the norm -- isn't a good fit for your use case, before going too deep down the rabbit hole. :) – Anthony Neace Apr 21 '17 at 04:53
  • Indeed, but i thank you all the same, and i think i managed to only put my head in the rabbit hole given the actual answer which i've just posted. Its pretty easy to fall back should amazon stop logging the image name, but since they decided to document it, i doubt they'll change it anytime soon. Looks a bit entrenched to me. – cineam mispelt Apr 21 '17 at 04:59
  • @cineammispelt Heh, nice. Good find. – Anthony Neace Apr 21 '17 at 05:03
1

Example from the system log (which i got from aws console view)

2016/12/26 14:36:12Z: AMI Origin Name: Windows_Server-2016-English-Full-Base

The equivalent powershell is:

Get-EC2ConsoleOutput

So here below in full (i'm new to powershell but i am pretty sure someone can wrap that into one character somehow)



    # read the system console log
    $consoleLog = Get-EC2ConsoleOutput $currentInstanceObj.InstanceId
    $consoleLogOutput = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($consoleLog.Output));

    # extract the lines that contain AMI Origin in them (there should be 2) - sort them so name i first and version is second
    $originLines  = $consoleLogOutput -split '[\r\n]' | Where-Object {$_.Contains("AMI Origin")} | Sort-Object

    # get the running name
    $originLine = $originLines[0]
    $originLineParts = $originLine.Split(':')
    $originName = $originLineParts[$originLineParts.Length - 1].Trim()
    "The origin name is $originName"

    # get the running version (slighly pointless since the code below doesn't care as we want the latest - but it's for verbosity)
    $originLine = $originLines[1]
    $originLineParts = $originLine.Split(':')
    $originVersion = $originLineParts[$originLineParts.Length - 1].Trim()
    "The origin version is $originVersion"

    # concatenate to get the original origin name (note: amazon have a naming pattern here - (name-version)
    $amiName = $originName + "-" + $originVersion
    "The original origin ami name is $amiName"

    #find the latest of the same name and report the difference
    $latestOriginObj = (Get-EC2Image -Filter @{ Name="name"; Values=($originName + "*")} | Sort-Object CreationDate -Descending | Select-Object -First 1)

    if($latestOriginObj.ImageId -ne $currentInstanceObj.ImageId)
    {
        "The ami has been upgraded from " + ($currentInstanceObj.ImageId) + " to " + ($latestOriginObj.ImageId)
    }

    #....so go ahead and use the $latestOriginObj.ImageId when you create a new instance    


And the knowledge source for that springs from these amazons docs

Excerpt below:

The AWS Management Console provides details about the AMI that you use to create an Amazon EC2 instance. The AMI ID field on the Description tab contains information including the Windows Server SKU, the architecture (32-bit or 64-bit), the date the AMI was created, and an AMI ID.

If an AMI has been made private or replaced by later versions and is no longer listed in the catalog, the AMI ID field states, "Cannot load detail for ami-xxxxx. You may not be permitted to view it." To determine which AMI was used to create the instance, you must open the system log. In the EC2 console, choose an instance, and from the context-menu (right-click) choose Instance Settings and then choose Get System Log. The date the AMI was created and the SKU are listed in the AMI Origin Version and AMI Origin Name fields.

cineam mispelt
  • 393
  • 1
  • 8