class Kitchen::Driver::Aws::StandardPlatform

Lets you grab StandardPlatform objects that help search for official AMIs in your region and tell you useful tidbits like usernames.

To use these, set your platform name to a supported platform name like:

centos rhel fedora freebsd macos ubuntu windows

The implementation will select the latest matching version and AMI.

You can specify a version and optional architecture as well:

windows-2012r2-i386 centos-7

Useful reference for platform AMIs: alestic.com/2014/01/ec2-ssh-username/

Constants

EBS_VOLUME_TYPES

The list of supported ebs volume types

SUPPORTED_ARCHITECTURES

The list of supported architectures

Attributes

architecture[R]

The architecture of the platform, e.g. i386, x86_64

@return [String]

@see SUPPORTED_ARCHITECTURESS

driver[R]

The driver.

@return [Kitchen::Driver::Ec2]

name[R]

The name of the platform (e.g. rhel, centos, etc.)

@return [String]

version[R]

The version of the platform (e.g. 7.1, 2008sp1, etc.)

@return [String]

Public Class Methods

from_image(driver, image) click to toggle source

Detect platform from an image.

@param driver [Kitchen::Driver::Ec2] The driver. @param image [Aws::Ec2::Image] The EC2 Image object.

@return [Kitchen::Driver::Aws::StandardPlatform]

# File lib/kitchen/driver/aws/standard_platform.rb, line 157
def self.from_image(driver, image)
  platforms.each_value do |platform|
    result = platform.from_image(driver, image)
    return result if result
  end
  nil
end
from_platform_string(driver, platform_string) click to toggle source

Instantiate a platform from a platform name.

@param driver [Kitchen::Driver::Ec2] The driver. @param platform_string [String] The platform string, e.g. “windows”,

"ubuntu-7.1", "centos-7-i386"

@return [Kitchen::Driver::Aws::StandardPlatform]

# File lib/kitchen/driver/aws/standard_platform.rb, line 142
def self.from_platform_string(driver, platform_string)
  platform, version, architecture = parse_platform_string(platform_string)
  return unless platform && platforms[platform]

  platforms[platform].new(driver, platform, version, architecture)
end
new(driver, name, version, architecture) click to toggle source

Create a new StandardPlatform object.

@param driver [Kitchen::Driver::Ec2] The driver. @param name [String] The name of the platform (rhel, centos, etc.) @param version [String] The version of the platform (7.1, 2008sp1, etc.) @param architecture [String] The architecture (i386, x86_64, arm64)

# File lib/kitchen/driver/aws/standard_platform.rb, line 52
def initialize(driver, name, version, architecture)
  @driver = driver
  @name = name
  @version = version
  @architecture = architecture
end
parse_platform_string(platform_string) click to toggle source
# File lib/kitchen/driver/aws/standard_platform.rb, line 165
def self.parse_platform_string(platform_string)
  platform, version = platform_string.split("-", 2)

  # If the right side is a valid architecture, use it as such
  # i.e. debian-i386 or windows-server-2012r2-i386
  if version && SUPPORTED_ARCHITECTURES.include?(version.split("-")[-1])
    # server-2012r2-i386 -> server-2012r2, -, i386
    version, _dash, architecture = version.rpartition("-")
    version = nil if version == ""
  end

  [platform, version, architecture]
end
platforms() click to toggle source

The list of StandardPlatform objects. StandardPlatforms register themselves with this.

@return Array

# File lib/kitchen/driver/aws/standard_platform.rb, line 125
def self.platforms
  @platforms ||= {}
end

Public Instance Methods

find_image(image_search) click to toggle source

Find the best matching image for the given image search.

@return [String] The image ID (e.g. ami-213984723)

# File lib/kitchen/driver/aws/standard_platform.rb, line 103
def find_image(image_search)
  driver.debug("Searching for images matching #{image_search} ...")
  # Convert to ec2 search format (pairs of name+values)
  filters = image_search.map do |key, value|
    { name: key.to_s, values: Array(value).map(&:to_s) }
  end

  # We prefer most recent first
  images = driver.ec2.resource.images(filters:)
  images = sort_images(images)
  show_returned_images(images)

  # Grab the best match
  images.first&.id
end
to_s() click to toggle source
# File lib/kitchen/driver/aws/standard_platform.rb, line 129
def to_s
  "#{name}#{version ? " #{version}" : ""}#{architecture ? " #{architecture}" : ""}"
end

Protected Instance Methods

prefer(images, &block) click to toggle source

Not supported yet: aix mac_os_x nexus solaris

# File lib/kitchen/driver/aws/standard_platform.rb, line 206
def prefer(images, &block)
  # Put the matching ones *before* the non-matching ones.
  matching, non_matching = images.partition(&block)
  matching + non_matching
end
sort_by_version(images) click to toggle source

Sort a list of images by their versions, from greatest to least.

This MUST perform a stable sort. (Note that ‘sort` and `sort_by` are not, by default, stable sorts in Ruby.)

Used by the default find_image. The default version calls platform_from_image() on each image, and interprets the versions as floats (7 < 7.1 < 8).

@param images [Array] The list of images to sort

@return [Array] A sorted list.

# File lib/kitchen/driver/aws/standard_platform.rb, line 194
def sort_by_version(images)
  # 7.1 -> [ img1, img2, img3 ]
  # 6 -> [ img4, img5 ]
  # ...
  images.group_by do |image|
    platform = self.class.from_image(driver, image)
    platform ? platform.version : nil
  end.sort_by { |k, _v| k ? k.to_f : nil }.reverse.flat_map { |_k, v| v }
end

Private Instance Methods

show_returned_images(images) click to toggle source
# File lib/kitchen/driver/aws/standard_platform.rb, line 233
def show_returned_images(images)
  if images.empty?
    driver.error("Search returned 0 images.")
  else
    driver.debug("Search returned #{images.size} images:")
    images.each do |image|
      platform = self.class.from_image(driver, image)
      if platform
        driver.debug("- #{image.name}: Detected #{platform}. #{driver.image_info(image)}")
      else
        driver.debug("- #{image.name}: No platform detected. #{driver.image_info(image)}")
      end
    end
  end
end
sort_images(images) click to toggle source
# File lib/kitchen/driver/aws/standard_platform.rb, line 214
def sort_images(images)
  # P6: We prefer more recent images over older ones
  images = images.sort_by(&:creation_date).reverse
  # P5: We prefer x86_64 over i386 (if available)
  images = prefer(images) { |image| image.architecture == "x86_64" }
  # P4: We prefer (SSD) (if available)
  images = prefer(images) do |image|
    image.block_device_mappings.any? do |b|
      b.device_name == image.root_device_name && b.ebs && EBS_VOLUME_TYPES.any?(b.ebs.volume_type)
    end
  end
  # P3: We prefer ebs over instance_store (if available)
  images = prefer(images) { |image| image.root_device_type == "ebs" }
  # P2: We prefer hvm (the modern standard)
  images = prefer(images) { |image| image.virtualization_type == "hvm" }
  # P1: We prefer the latest version over anything else
  sort_by_version(images)
end