module MotherBrain::Mixin::AttributeSetting

Public Instance Methods

set_component_versions(env_id, plugin, component_versions) click to toggle source

Set the appropriate attributes at the environment level to the desired version for each component given

@param [String] env_id

the name identifier of the environment to modify

@param [MB::Plugin] plugin

the plugin to use for finding the appropriate version attributes

@param [Hash] component_versions

Hash of components and the versions to set them to

@raise [MB::EnvironmentNotFound] if the environment does not exist

@example setting the versions of multiple components on an environment

set_component_versions("test-environment",
  "component_one" => "1.0.0",
  "component_two" => "2.3.0"
)
# File lib/mb/mixin/attribute_setting.rb, line 28
def set_component_versions(env_id, plugin, component_versions)
  default_attributes = Hash.new

  component_versions.each do |component_name, version|
    version_hash = Hash.from_dotted_path(version_attribute(plugin, component_name), version)
    default_attributes.deep_merge!(version_hash)
  end

  log.info "Setting component versions #{component_versions}"

  unless env = chef_connection.environment.find(env_id)
    raise EnvironmentNotFound.new(env_id)
  end

  env.default_attributes.merge!(default_attributes)
  env.save
end
set_cookbook_versions(env_id, cookbook_versions) click to toggle source

Lock the cookbook versions on the target environment from the given hash of cookbooks and versions

@param [String] env_id

the name identifier of the environment to modify

@param [Hash] cookbook_versions

Hash of cookbooks and the versions to set them to

@raise [MB::EnvironmentNotFound] if the environment does not exist

@example setting cookbook versions on an environment

set_cookbook_versions("test-environment",
  "league" => "1.74.2",
  "pvpnet" => "3.2.0"
)

@raise [ArgumentError] if given invalid version constraints

# File lib/mb/mixin/attribute_setting.rb, line 64
def set_cookbook_versions(env_id, cookbook_versions)
  cookbook_versions = expand_constraints(expand_latest_versions(cookbook_versions))
  satisfies_constraints?(cookbook_versions)
  log.info "Setting cookbook versions #{cookbook_versions}"

  unless env = chef_connection.environment.find(env_id)
    raise EnvironmentNotFound.new(env_id)
  end

  env.cookbook_versions.merge!(cookbook_versions)
  env.save
end
set_environment_attributes(env_id, new_attributes) click to toggle source

Set environment level attributes on an environment from a hash containing keys identifying attributes using the dot notation syntax and values of those attributes as values.

@param [String] env_id

the name identifier of the environment to modify

@param [Hash] new_attributes

Hash of attributes and values

@example setting multiple attributes on an environment

set_environment_attributes("test-environment",
  "foo"      => "bar",
  "baz.quux" => 42
)
# File lib/mb/mixin/attribute_setting.rb, line 92
def set_environment_attributes(env_id, new_attributes)
  default_attributes = Hash.new

  new_attributes.each do |attribute, value|
    attribute_hash = Hash.from_dotted_path(attribute.to_s, value.to_s)
    default_attributes.deep_merge!(attribute_hash)
  end

  set_environment_attributes_from_hash(env_id, default_attributes)
end
set_environment_attributes_from_file(env_id, filepath, type = :json) click to toggle source

Set environment level attributes on an environment from the contents of the file at the given filepath

@param [String] env_id

the name of the environment to modify

@param [String] filepath

path to the file to read attributes from

@param [Symbol] type

the type of the contents found within the file

@raise [InvalidAttributesFile]

if the contents of the attributes file are missing or not well formed

@raise [ArgumentError]

if an unknown value for the 'type' parameter is specified
# File lib/mb/mixin/attribute_setting.rb, line 145
def set_environment_attributes_from_file(env_id, filepath, type = :json)
  contents = File.read(filepath)

  case type
  when :json
    set_environment_attributes_from_json(env_id, contents)
  else
    raise ArgumentError, "cannot read attributes from files of type: #{type}"
  end
rescue MultiJson::DecodeError => ex
  raise InvalidAttributesFile, "Invalid JSON in #{filepath}: #{ex}"
end
set_environment_attributes_from_hash(env_id, new_attributes) click to toggle source

Set arbitrary attributes at the environment level

@param [String] env_id

the name of the environment to modify

@param [Hash] new_attributes

Hash of attributes to set on the environment

@raise [MB::EnvironmentNotFound] if the environment does not exist

@example setting multiple attributes on an environment

set_environment_attributes_from_hash("test-environment",
  "foo" => "bar",
  "baz  => {
    "quux" => 42
  }
)
# File lib/mb/mixin/attribute_setting.rb, line 120
def set_environment_attributes_from_hash(env_id, new_attributes)
  log.info "Setting environment attributes: #{new_attributes}"

  unless env = chef_connection.environment.find(env_id)
    raise EnvironmentNotFound.new(env_id)
  end

  env.default_attributes.deep_merge!(new_attributes)
  env.save
end
set_environment_attributes_from_json(env_id, json) click to toggle source

Set environment level attributes on an environment from the given JSON string

@param [String] env_id

the name of the environment to modify

@param [String] json

the json to use as attributes
# File lib/mb/mixin/attribute_setting.rb, line 164
def set_environment_attributes_from_json(env_id, json)
  set_environment_attributes_from_hash(env_id, MultiJson.decode(json))
end

Private Instance Methods

expand_constraints(cookbook_versions) click to toggle source

Expand constraints strings given to their fully qualified constraint operators

@param [Hash] cookbook_versions

Hash of cookbooks and the versions

@raise [ArgumentError] if the array of constraints contains an entry which is not in the

correct version constraint format

@example

expand_constraints(
  "league" => "1.74.2",
  "pvpnet" => ">= 1.2.3"
)

# => { "league" => "= 1.74.2", "pvpnet" => ">= 1.2.3" }

@return [Hash]

# File lib/mb/mixin/attribute_setting.rb, line 234
def expand_constraints(cookbook_versions)
  expanded = cookbook_versions.collect do |name, constraint|
    [name, Semverse::Constraint.new(constraint).to_s]
  end

  Hash[expanded]
rescue Semverse::InvalidConstraintFormat => ex
  raise ArgumentError, ex
end
expand_latest_versions(cookbook_versions) click to toggle source

Expand the “latest” cookbook versions to the latest verison number for the cookbook

@param [Hash] cookbook_versions

Hash of cookbooks and the versions

@example expanding versions when 3.1.0 is the latest pvpnet cookbook

expand_latest_versions(
  "league" => "1.74.2",
  "pvpnet" => "latest"
)

# => {"league" => "1.74.2", "pvpnet" => "3.1.0"}
# File lib/mb/mixin/attribute_setting.rb, line 205
def expand_latest_versions(cookbook_versions)
  expanded_cookbook_versions = cookbook_versions.map do |name, version|
    if version.downcase == "latest"
      version = chef_connection.cookbook.latest_version(name)
    end

    [name, version]
  end

  Hash[expanded_cookbook_versions]
end
satisfies_constraints?(cookbook_versions) click to toggle source

Ensure the chef server can satisfy the desired cookbook version constraints

@param [Hash] cookbook_versions

Hash of cookbooks and the versions

@raise [MB::CookbookConstraintNotSatisfied]

if the constraints cannot be satisfied
# File lib/mb/mixin/attribute_setting.rb, line 251
def satisfies_constraints?(cookbook_versions)
  failures = cookbook_versions.concurrent_map do |name, constraint|
    if chef_connection.cookbook.satisfy(name, constraint).nil?
      "#{name} (#{constraint})"
    end
  end.compact

  unless failures.empty?
    raise MB::CookbookConstraintNotSatisfied,
      "couldn't satisfy constraints for cookbook version(s): #{failures.join(', ')}"
  end
end
version_attribute(plugin, component_name) click to toggle source

retrieve the version attribute of a given component and raise if the component is not versioned

@param [MB::Plugin] plugin @param [#to_s] component_name

@raise [ComponentNotVersioned]

@return [String]

# File lib/mb/mixin/attribute_setting.rb, line 179
def version_attribute(plugin, component_name)
  result = plugin.component!(component_name).version_attribute

  unless result
    raise ComponentNotVersioned.new component_name
  end

  log.info "Component '#{component_name}' versioned with '#{result}'"

  result
end