class Kitchen::Microwave::Platforms

The platforms config is more complex, needs to be generated based on what the cookbook metadata advertises support for.

@author Jonathan Hartman <jonathan.hartman@socrata.com>

Public Class Methods

new(cookbook_dir, excludes = []) click to toggle source

Build a set of platforms based on the metadata's advertised supported platforms*Chef versions. Each platform gets a config to install the appropriate init system and start it as PID 1, and do anything else that might be common to make it behave enough like a regular VM for testing.

Instantiating requires a path to the cookdook under test and can accept an optional set of excluded platforms of the format:

[
  {
    'name' => 'ubuntu',
    'version' => '14.04',
    'chef' => '14'
  },
  {
    'name' => 'debian',
    # 'version' => 'implicit "all"'
    # 'chef' => 'implicit "all"'
  }

@param [String] cookbook_dir path to the cookbook under test @param [Array<Hash>] an array of platform information to exclude

@return [Kitchen::Microwave::Platforms] the new platforms object

# File lib/kitchen/microwave/platforms.rb, line 74
def initialize(cookbook_dir, excludes = [])
  @cookbook_dir = cookbook_dir
  @excludes = excludes || []

  supported_chefs.each do |chef|
    supported_platforms.each do |name, versions|
      versions.each do |version|
        self << platform_for(name, version, chef) unless \
          excluded?(name, version, chef)
      end
    end
  end
end

Public Instance Methods

excluded?(name, version, chef) click to toggle source

Determine if a particular platform name, version, and chef combo is globally excluded.

@param [String] name the platform name @param [String] version the platform version @param [String] chef the Chef version

@return [TrueClass, FalseClass] whether it is excluded

# File lib/kitchen/microwave/platforms.rb, line 121
def excluded?(name, version, chef)
  @excludes.each do |exc|
    return true if ['', name].include?(exc['name'].to_s) && \
                   ['', version].include?(exc['version'].to_s) && \
                   ['', chef].include?(exc['chef'].to_s)
  end
  false
end
metadata() click to toggle source

Read and store the local cookbook's metadata.

@return [Chef::Cookbook::Metadata] the cookbook metadata

# File lib/kitchen/microwave/platforms.rb, line 191
def metadata
  @metadata ||= begin
    md = Chef::Cookbook::Metadata.new
    md.from_file(File.join(@cookbook_dir, 'metadata.rb'))
    md
  end
end
metadata_platforms() click to toggle source

Pull the supported platforms out of the metadata and do any required transformations to them.

@return [Hash] a hash of platform_name => requirement_string

# File lib/kitchen/microwave/platforms.rb, line 170
def metadata_platforms
  @metadata_platforms ||= begin
    metadata.platforms.each_with_object({}) do |(name, req), hsh|
      # Amazon Linux is named "amazon" in Chef metadata but "amazonlinux"
      # in Docker Hub.
      name = 'amazonlinux' if name == 'amazon'

      # Assume that CentOS' e.g. "7" tag in Docker Hub will satisfy an
      # e.g. "~> 7.4" requirement string.
      req = req.split('.').first if name == 'centos'

      hsh[name] = req
    end
  end
end
platform_for(name, version, chef) click to toggle source

Build the stanza for a single platform+version+Chef version, including any intermediate steps we use to make the Docker container behave more like a real VM.

@param [String] name the platform name @param [String] version the platform version @param [String] chef the Chef version

@return [Hash] a single platform stanza

# File lib/kitchen/microwave/platforms.rb, line 99
def platform_for(name, version, chef)
  file = File.expand_path("platforms/#{name}/#{version}.json", __dir__)
  data = JSON.parse(File.read(file))
  {
    'name' => "#{name}-#{version}-chef-#{chef}",
    'driver' => {
      'image' => "#{name}:#{version}",
      'chef_version' => chef
    }
  }.rmerge(data)
end
supported_chefs() click to toggle source

Look at the supported Chef versions in the metadata to figure out which should be tested against.

@return [Array<String>] an array of major Chef versions/Docker images

# File lib/kitchen/microwave/platforms.rb, line 153
def supported_chefs
  @supported_chefs ||= POTENTIAL_CHEFS.select do |chef|
    metadata.chef_versions.find do |cv|
      # The Docker tag e.g. "14" should always be the newest release of
      # that major version and satisfy e.g. "~> 14.2".
      Gem::Requirement.new(cv.requirement.to_s.split('.').first)
                      .satisfied_by?(Gem::Version.new(chef))
    end
  end
end
supported_platforms() click to toggle source

Look at the supported platforms in the metadata and figure out what platforms and versions should be tested.

@return [Hash] a hash of platform => [version1, version2…]

# File lib/kitchen/microwave/platforms.rb, line 136
def supported_platforms
  @supported_platforms ||= metadata_platforms
                           .each_with_object({}) do |(name, req), hsh|
    req = Gem::Requirement.new(req)
    POTENTIAL_PLATFORMS[name].to_a.each do |version|
      hsh[name] ||= []
      hsh[name] << version if req.satisfied_by?(Gem::Version.new(version))
    end
  end
end