Add package providers and version lookup
This commits adds modified version of the Puppet Package type. It includes code that looks for package version in /etc/versions.yaml file if the package is going to be installed instead of just installing the first available version. This lookup will be initiated only is you pass :installed or :present to the package's ensure property. Passing :latest, :absent or explicit version string will cause the default behaviour. Lookups will be performed only for apt and yum providers. Yum and Apt providers in this patch are hacked to support transactional rollbacks. When the provider is updating the package from one version to another it saves the diff of packages to a file and if it’s ever asked to install the previous version again the provider takes the diff file and installs the previous package versions and their dependencies. Change-Id: I84e4b7540f9e72ceb2e1dee0762184d3e2b4356c Implements: blueprint patch-openstack
This commit is contained in:
parent
d7b58f1856
commit
9b76d1ae6d
@ -19,7 +19,7 @@ class ceph::params {
|
|||||||
$dir_httpd_ssl = '/etc/httpd/ssl/'
|
$dir_httpd_ssl = '/etc/httpd/ssl/'
|
||||||
|
|
||||||
package { ['ceph', 'redhat-lsb-core','ceph-deploy', 'pushy',]:
|
package { ['ceph', 'redhat-lsb-core','ceph-deploy', 'pushy',]:
|
||||||
ensure => latest,
|
ensure => installed,
|
||||||
}
|
}
|
||||||
|
|
||||||
file {'/etc/sudoers.d/ceph':
|
file {'/etc/sudoers.d/ceph':
|
||||||
@ -44,7 +44,7 @@ class ceph::params {
|
|||||||
$dir_httpd_ssl = '/etc/apache2/ssl/'
|
$dir_httpd_ssl = '/etc/apache2/ssl/'
|
||||||
|
|
||||||
package { ['ceph','ceph-deploy', 'python-pushy', ]:
|
package { ['ceph','ceph-deploy', 'python-pushy', ]:
|
||||||
ensure => latest,
|
ensure => installed,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ class ceph::radosgw (
|
|||||||
$::ceph::params::package_fastcgi,
|
$::ceph::params::package_fastcgi,
|
||||||
$::ceph::params::package_libnss,
|
$::ceph::params::package_libnss,
|
||||||
]:
|
]:
|
||||||
ensure => 'latest',
|
ensure => 'installed',
|
||||||
}
|
}
|
||||||
|
|
||||||
service { 'radosgw':
|
service { 'radosgw':
|
||||||
@ -69,7 +69,7 @@ class ceph::radosgw (
|
|||||||
defined($::ceph::params::package_httpd) or
|
defined($::ceph::params::package_httpd) or
|
||||||
defined($::ceph::params::service_httpd) ) {
|
defined($::ceph::params::service_httpd) ) {
|
||||||
package {$::ceph::params::package_httpd:
|
package {$::ceph::params::package_httpd:
|
||||||
ensure => 'latest',
|
ensure => 'installed',
|
||||||
}
|
}
|
||||||
service { 'httpd':
|
service { 'httpd':
|
||||||
ensure => 'running',
|
ensure => 'running',
|
||||||
|
@ -7,7 +7,7 @@ class cinder::api (
|
|||||||
$keystone_auth_host = 'localhost',
|
$keystone_auth_host = 'localhost',
|
||||||
$keystone_auth_port = '35357',
|
$keystone_auth_port = '35357',
|
||||||
$keystone_auth_protocol = 'http',
|
$keystone_auth_protocol = 'http',
|
||||||
$package_ensure = 'latest',
|
$package_ensure = 'installed',
|
||||||
$bind_host = '0.0.0.0',
|
$bind_host = '0.0.0.0',
|
||||||
$enabled = true,
|
$enabled = true,
|
||||||
$cinder_rate_limits = undef
|
$cinder_rate_limits = undef
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#
|
#
|
||||||
class cinder::scheduler (
|
class cinder::scheduler (
|
||||||
$package_ensure = 'latest',
|
$package_ensure = 'installed',
|
||||||
$enabled = true
|
$enabled = true
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# $volume_name_template = volume-%s
|
# $volume_name_template = volume-%s
|
||||||
class cinder::volume (
|
class cinder::volume (
|
||||||
$package_ensure = 'latest',
|
$package_ensure = 'installed',
|
||||||
$enabled = true
|
$enabled = true
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
@ -223,7 +223,7 @@ class galera (
|
|||||||
if $::galera::params::mysql_version {
|
if $::galera::params::mysql_version {
|
||||||
$wsrep_version = $::galera::params::mysql_version
|
$wsrep_version = $::galera::params::mysql_version
|
||||||
} else {
|
} else {
|
||||||
$wsrep_version = 'latest'
|
$wsrep_version = 'installed'
|
||||||
}
|
}
|
||||||
package { "MySQL-server":
|
package { "MySQL-server":
|
||||||
ensure => $wsrep_version,
|
ensure => $wsrep_version,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
# uses the keystone packages
|
# uses the keystone packages
|
||||||
# to ensure that we use the latest precise packages
|
# to ensure that we use the installed precise packages
|
||||||
Exec { logoutput => 'on_failure' }
|
Exec { logoutput => 'on_failure' }
|
||||||
|
|
||||||
node glance {
|
node glance {
|
||||||
|
@ -7,7 +7,7 @@ class glance::backend::ceph(
|
|||||||
) inherits glance::api {
|
) inherits glance::api {
|
||||||
|
|
||||||
package {'python-ceph':
|
package {'python-ceph':
|
||||||
ensure => latest,
|
ensure => installed,
|
||||||
}
|
}
|
||||||
|
|
||||||
glance_api_config {
|
glance_api_config {
|
||||||
|
@ -30,7 +30,7 @@ class keystone::dev::install(
|
|||||||
'libldap2-dev',
|
'libldap2-dev',
|
||||||
'sqlite3'
|
'sqlite3'
|
||||||
]:
|
]:
|
||||||
ensure => latest,
|
ensure => installed,
|
||||||
}
|
}
|
||||||
|
|
||||||
vcsrepo { $source_dir:
|
vcsrepo { $source_dir:
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
# == Parameters
|
# == Parameters
|
||||||
#
|
#
|
||||||
# [package_ensure] Desired ensure state of packages. Optional. Defaults to present.
|
# [package_ensure] Desired ensure state of packages. Optional. Defaults to present.
|
||||||
# accepts latest or specific versions.
|
# accepts installed or specific versions.
|
||||||
# [bind_host] Host that keystone binds to.
|
# [bind_host] Host that keystone binds to.
|
||||||
# [bind_port] Port that keystone binds to.
|
# [bind_port] Port that keystone binds to.
|
||||||
# [public_port]
|
# [public_port]
|
||||||
|
@ -95,11 +95,11 @@ class mysql::params {
|
|||||||
$datadir = '/var/db/mysql'
|
$datadir = '/var/db/mysql'
|
||||||
$service_name = 'mysql-server'
|
$service_name = 'mysql-server'
|
||||||
$client_package_name = 'databases/mysql55-client'
|
$client_package_name = 'databases/mysql55-client'
|
||||||
$client_version = 'latest'
|
$client_version = 'installed'
|
||||||
$server_package_name = 'databases/mysql55-server'
|
$server_package_name = 'databases/mysql55-server'
|
||||||
$server_version = 'latest'
|
$server_version = 'installed'
|
||||||
$shared_package_name = 'databases/mysql55-server'
|
$shared_package_name = 'databases/mysql55-server'
|
||||||
$shared_version = 'latest'
|
$shared_version = 'installed'
|
||||||
$socket = '/tmp/mysql.sock'
|
$socket = '/tmp/mysql.sock'
|
||||||
$pidfile = '/var/db/mysql/mysql.pid'
|
$pidfile = '/var/db/mysql/mysql.pid'
|
||||||
$config_file = '/var/db/mysql/my.cnf'
|
$config_file = '/var/db/mysql/my.cnf'
|
||||||
|
@ -24,7 +24,7 @@ define nailgun::venv::pip(
|
|||||||
unless => "$venv/bin/pip freeze | grep -e $grep_regex"
|
unless => "$venv/bin/pip freeze | grep -e $grep_regex"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
elsif $ensure == 'latest' {
|
elsif $ensure == 'installed' {
|
||||||
exec { "pip install $name":
|
exec { "pip install $name":
|
||||||
command => "$venv/bin/pip install $opts -U $package",
|
command => "$venv/bin/pip install $opts -U $package",
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,7 @@ class ntp($servers=undef,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if $autoupdate == true {
|
if $autoupdate == true {
|
||||||
$package_ensure = latest
|
$package_ensure = installed
|
||||||
} elsif $autoupdate == false {
|
} elsif $autoupdate == false {
|
||||||
$package_ensure = present
|
$package_ensure = present
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
$fuel_settings = parseyaml($astute_settings_yaml)
|
$fuel_settings = parseyaml($astute_settings_yaml)
|
||||||
|
|
||||||
$openstack_version = {
|
$openstack_version = {
|
||||||
'keystone' => 'latest',
|
'keystone' => 'installed',
|
||||||
'glance' => 'latest',
|
'glance' => 'installed',
|
||||||
'horizon' => 'latest',
|
'horizon' => 'installed',
|
||||||
'nova' => 'latest',
|
'nova' => 'installed',
|
||||||
'novncproxy' => 'latest',
|
'novncproxy' => 'installed',
|
||||||
'cinder' => 'latest',
|
'cinder' => 'installed',
|
||||||
}
|
}
|
||||||
|
|
||||||
tag("${::fuel_settings['deployment_id']}::${::fuel_settings['environment']}")
|
tag("${::fuel_settings['deployment_id']}::${::fuel_settings['environment']}")
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
require 'facter'
|
require 'facter'
|
||||||
|
|
||||||
# This file is created and managed by Astute
|
# This file is created and managed by Astute
|
||||||
astute_settings_path = '/etc/astute.yaml'
|
|
||||||
|
|
||||||
# FIXME: this code do not work with Ruby 2.1
|
|
||||||
#return unless File.exist?(astute_settings_path)
|
|
||||||
|
|
||||||
Facter.add('astute_settings_yaml') do
|
Facter.add('astute_settings_yaml') do
|
||||||
setcode { File.read(astute_settings_path) }
|
setcode do
|
||||||
|
astute_settings_path = '/etc/astute.yaml'
|
||||||
|
if File.readable? astute_settings_path
|
||||||
|
File.read astute_settings_path
|
||||||
|
else
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
2
deployment/puppet/package/.rspec
Normal file
2
deployment/puppet/package/.rspec
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
-f doc
|
||||||
|
--color
|
@ -1,3 +1,5 @@
|
|||||||
|
require 'yaml'
|
||||||
|
|
||||||
Puppet::Type.type(:package).provide :apt, :parent => :dpkg, :source => :dpkg do
|
Puppet::Type.type(:package).provide :apt, :parent => :dpkg, :source => :dpkg do
|
||||||
# Provide sorting functionality
|
# Provide sorting functionality
|
||||||
include Puppet::Util::Package
|
include Puppet::Util::Package
|
||||||
@ -9,6 +11,7 @@ Puppet::Type.type(:package).provide :apt, :parent => :dpkg, :source => :dpkg do
|
|||||||
commands :aptget => "/usr/bin/apt-get"
|
commands :aptget => "/usr/bin/apt-get"
|
||||||
commands :aptcache => "/usr/bin/apt-cache"
|
commands :aptcache => "/usr/bin/apt-cache"
|
||||||
commands :preseed => "/usr/bin/debconf-set-selections"
|
commands :preseed => "/usr/bin/debconf-set-selections"
|
||||||
|
commands :dpkgquery => '/usr/bin/dpkg-query'
|
||||||
|
|
||||||
defaultfor :operatingsystem => [:debian, :ubuntu]
|
defaultfor :operatingsystem => [:debian, :ubuntu]
|
||||||
|
|
||||||
@ -36,36 +39,169 @@ Puppet::Type.type(:package).provide :apt, :parent => :dpkg, :source => :dpkg do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Install a package using 'apt-get'. This function needs to support
|
# @param pkg <Hash,TrueClass,FalseClass,Symbol,String>
|
||||||
# installing a specific version.
|
# @param action <Symbol>
|
||||||
def install
|
def install_cmd(pkg)
|
||||||
self.run_preseed if @resource[:responsefile]
|
|
||||||
should = @resource[:ensure]
|
|
||||||
|
|
||||||
checkforcdrom
|
|
||||||
cmd = %w{-q -y}
|
cmd = %w{-q -y}
|
||||||
|
|
||||||
if config = @resource[:configfiles]
|
config = @resource[:configfiles]
|
||||||
if config == :keep
|
if config == :keep
|
||||||
cmd << "-o" << 'DPkg::Options::=--force-confold'
|
cmd << "-o" << 'DPkg::Options::=--force-confold'
|
||||||
else
|
else
|
||||||
cmd << "-o" << 'DPkg::Options::=--force-confnew'
|
cmd << "-o" << 'DPkg::Options::=--force-confnew'
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
str = @resource[:name]
|
cmd << '--force-yes'
|
||||||
case should
|
cmd << :install
|
||||||
when true, false, Symbol
|
|
||||||
# pass
|
if pkg.is_a? Hash
|
||||||
|
# make install string from package hash
|
||||||
|
cmd += pkg.map do |p|
|
||||||
|
if p[1] == :absent
|
||||||
|
"#{p[0]}-"
|
||||||
else
|
else
|
||||||
# Add the package version and --force-yes option
|
"#{p[0]}=#{p[1]}"
|
||||||
str += "=#{should}"
|
end
|
||||||
cmd << "--force-yes"
|
end
|
||||||
|
elsif pkg.is_a? String
|
||||||
|
# install a specific version
|
||||||
|
cmd << "#{@resource[:name]}=#{pkg}"
|
||||||
|
else
|
||||||
|
# install any version
|
||||||
|
cmd << @resource[:name]
|
||||||
end
|
end
|
||||||
|
|
||||||
cmd << :install << str
|
cmd
|
||||||
|
end
|
||||||
|
|
||||||
aptget(*cmd)
|
# Install a package using 'apt-get'. This function needs to support
|
||||||
|
# installing a specific version.
|
||||||
|
def install
|
||||||
|
self.run_preseed if @resource[:responsefile]
|
||||||
|
should = @resource[:ensure]
|
||||||
|
@file_dir = '/var/lib/puppet/rollback'
|
||||||
|
|
||||||
|
checkforcdrom
|
||||||
|
|
||||||
|
name = @resource[:name]
|
||||||
|
from = @property_hash[:ensure]
|
||||||
|
to = @resource[:ensure]
|
||||||
|
to = latest if to == :latest
|
||||||
|
|
||||||
|
Puppet.debug "Installing package #{name} from #{from} to #{to}"
|
||||||
|
|
||||||
|
rollback_file = File.join @file_dir, "#{name}_#{to}_#{from}.yaml"
|
||||||
|
diff = read_diff rollback_file
|
||||||
|
|
||||||
|
if diff.is_a?(Hash) && diff.key?('installed') && diff.key?('removed')
|
||||||
|
# rollback
|
||||||
|
Puppet.debug "Found rollback file at #{rollback_file}"
|
||||||
|
installed = diff['installed']
|
||||||
|
removed = diff['removed']
|
||||||
|
|
||||||
|
# calculate package sets
|
||||||
|
to_update = package_updates removed, installed
|
||||||
|
to_install = package_diff removed, installed
|
||||||
|
to_remove = package_diff installed, removed, true
|
||||||
|
|
||||||
|
Puppet.debug "Install: #{to_install.map {|p| "#{p[0]}=#{p[1]}" }. join ' '}" if to_install.any?
|
||||||
|
Puppet.debug "Remove: #{to_remove.map {|p| "#{p[0]}=#{p[1]}" }. join ' '}" if to_remove.any?
|
||||||
|
Puppet.debug "Update: #{to_update.map {|p| "#{p[0]}=#{p[1]}" }. join ' '}" if to_update.any?
|
||||||
|
|
||||||
|
# combine package lists to a single list
|
||||||
|
to_remove.each_pair {|k,v| to_remove.store k, :absent}
|
||||||
|
all_packages = to_install.merge(to_update).merge to_remove
|
||||||
|
|
||||||
|
if all_packages.any?
|
||||||
|
Puppet.debug "All: #{all_packages.map {|p| "#{p[0]}=#{p[1]}" }. join ' '}" if all_packages.any?
|
||||||
|
cmd = install_cmd all_packages
|
||||||
|
aptget *cmd
|
||||||
|
end
|
||||||
|
elsif from.is_a?(String) && to.is_a?(String)
|
||||||
|
# update
|
||||||
|
cmd = install_cmd should
|
||||||
|
before,after = aptget_with_changes cmd
|
||||||
|
diff = make_package_diff before, after
|
||||||
|
file_path = File.join @file_dir, "#{name}_#{from}_#{to}.yaml"
|
||||||
|
Puppet.notice "Saving diff file to #{file_path}"
|
||||||
|
save_diff file_path, diff
|
||||||
|
else
|
||||||
|
# just install the package
|
||||||
|
cmd = install_cmd should
|
||||||
|
aptget *cmd
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def aptget_with_changes(cmd)
|
||||||
|
before = pkg_list
|
||||||
|
aptget *cmd
|
||||||
|
after = pkg_list
|
||||||
|
[ before, after ]
|
||||||
|
end
|
||||||
|
|
||||||
|
def make_package_diff(before, after)
|
||||||
|
installed = package_diff after, before
|
||||||
|
removed = package_diff before, after
|
||||||
|
{ 'installed' => installed, 'removed' => removed }
|
||||||
|
end
|
||||||
|
|
||||||
|
# saves diff hash into a file
|
||||||
|
# @param file_path <String>
|
||||||
|
# @param diff <Hash[String]>
|
||||||
|
def save_diff(file_path, diff)
|
||||||
|
require 'yaml'
|
||||||
|
Dir.mkdir @file_dir unless File.directory? @file_dir
|
||||||
|
File.open(file_path, 'w') { |file| file.write YAML.dump(diff) + "\n" }
|
||||||
|
end
|
||||||
|
|
||||||
|
# reads diff hash from a file
|
||||||
|
# @param file_path <String>
|
||||||
|
# @returns <Hash[String]>
|
||||||
|
def read_diff(file_path)
|
||||||
|
return unless File.readable? file_path
|
||||||
|
diff = YAML.load_file file_path
|
||||||
|
return unless diff.is_a? Hash
|
||||||
|
diff
|
||||||
|
end
|
||||||
|
|
||||||
|
# Substract packages in hash b from packages in hash a
|
||||||
|
# in noval is true only package name matters and version is ignored
|
||||||
|
# @param a <Hash[String]>
|
||||||
|
# @param b <Hash[String]>
|
||||||
|
# @param ignore_versions <TrueClass,FalseClass>
|
||||||
|
def package_diff(a, b, ignore_versions = false)
|
||||||
|
result = a.dup
|
||||||
|
b.each_pair do |k, v|
|
||||||
|
if a.key? k
|
||||||
|
if a[k] == v or ignore_versions
|
||||||
|
result.delete k
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
result
|
||||||
|
end
|
||||||
|
|
||||||
|
# find package names in both a and b hashes
|
||||||
|
# values are taken from a
|
||||||
|
# @param a <Hash[String]>
|
||||||
|
# @param b <Hash[String]>
|
||||||
|
def package_updates(a, b)
|
||||||
|
common_keys = a.keys & b.keys
|
||||||
|
common_keys.inject({}) { |result, p| result.merge({p => a[p]}) }
|
||||||
|
end
|
||||||
|
|
||||||
|
def pkg_list
|
||||||
|
packages = {}
|
||||||
|
raw_pkgs = dpkgquery [ '--show', '-f=${Package}|${Version}|${Status}\n' ]
|
||||||
|
raw_pkgs.split("\n").each do |l|
|
||||||
|
line = l.split('|')
|
||||||
|
next unless line[2] == 'install ok installed'
|
||||||
|
name = line[0]
|
||||||
|
version = line[1]
|
||||||
|
next if !name || !version
|
||||||
|
packages.store name, version
|
||||||
|
end
|
||||||
|
packages
|
||||||
end
|
end
|
||||||
|
|
||||||
# What's the latest package version available?
|
# What's the latest package version available?
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
require 'puppet/util/package'
|
require 'puppet/util/package'
|
||||||
|
require 'yaml'
|
||||||
|
|
||||||
Puppet::Type.type(:package).provide :yum, :parent => :rpm, :source => :rpm do
|
Puppet::Type.type(:package).provide :yum, :parent => :rpm, :source => :rpm do
|
||||||
desc "Support via `yum`.
|
desc "Support via `yum`.
|
||||||
@ -54,11 +55,60 @@ Puppet::Type.type(:package).provide :yum, :parent => :rpm, :source => :rpm do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def pkg_list
|
||||||
|
raw_pkgs = rpm [ '-q', '-a', '--queryformat', '%{NAME}|%{VERSION}-%{RELEASE}\n' ]
|
||||||
|
pkgs = {}
|
||||||
|
raw_pkgs.split("\n").each do |l|
|
||||||
|
line = l.split '|'
|
||||||
|
name = line[0]
|
||||||
|
version = line[1]
|
||||||
|
next if !name || !version
|
||||||
|
pkgs.store name, version
|
||||||
|
end
|
||||||
|
pkgs
|
||||||
|
end
|
||||||
|
|
||||||
|
# Substract packages in hash b from packages in hash a
|
||||||
|
# in noval is true only package name matters and version is ignored
|
||||||
|
# @param a <Hash[String]>
|
||||||
|
# @param b <Hash[String]>
|
||||||
|
# @param ignore_versions <TrueClass,FalseClass>
|
||||||
|
def package_diff(a, b, ignore_versions = false)
|
||||||
|
result = a.dup
|
||||||
|
b.each_pair do |k, v|
|
||||||
|
if a.key? k
|
||||||
|
if a[k] == v or ignore_versions
|
||||||
|
result.delete k
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
result
|
||||||
|
end
|
||||||
|
|
||||||
|
# find package names in both a and b hashes
|
||||||
|
# values are taken from a
|
||||||
|
# @param a <Hash[String]>
|
||||||
|
# @param b <Hash[String]>
|
||||||
|
def package_updates(a, b)
|
||||||
|
common_keys = a.keys & b.keys
|
||||||
|
common_keys = a.keys & b.keys
|
||||||
|
common_keys.inject({}) { |result, p| result.merge({p => a[p]}) }
|
||||||
|
end
|
||||||
|
|
||||||
def install
|
def install
|
||||||
should = @resource.should(:ensure)
|
should = @resource.should(:ensure)
|
||||||
self.debug "Ensuring => #{should}"
|
self.debug "Ensuring => #{should}"
|
||||||
wanted = @resource[:name]
|
wanted = @resource[:name]
|
||||||
operation = :install
|
operation = :install
|
||||||
|
yum_options = %w(-d 0 -e 0 -y)
|
||||||
|
|
||||||
|
@file_dir = '/var/lib/puppet/rollback'
|
||||||
|
|
||||||
|
from = @property_hash[:ensure]
|
||||||
|
to = should
|
||||||
|
name = @resource[:name]
|
||||||
|
|
||||||
|
Puppet.notice "Installing package #{name} from #{from} to #{to}"
|
||||||
|
|
||||||
case should
|
case should
|
||||||
when true, false, Symbol
|
when true, false, Symbol
|
||||||
@ -74,9 +124,37 @@ Puppet::Type.type(:package).provide :yum, :parent => :rpm, :source => :rpm do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
yum "-d", "0", "-e", "0", "-y", operation, wanted
|
rollback_file = File.join @file_dir, "#{name}_#{to}_#{from}.yaml"
|
||||||
|
diff = read_diff rollback_file
|
||||||
|
|
||||||
is = self.query
|
if diff.is_a?(Hash) && diff.key?('installed') && diff.key?('removed')
|
||||||
|
# rollback
|
||||||
|
# reverse the update process instead of usuall install
|
||||||
|
Puppet.debug "Found rollback file at #{rollback_file}"
|
||||||
|
installed = diff['installed']
|
||||||
|
removed = diff['removed']
|
||||||
|
# calculate package sets
|
||||||
|
to_update = package_updates removed, installed
|
||||||
|
to_install = package_diff removed, installed
|
||||||
|
to_remove = package_diff installed, removed, true
|
||||||
|
Puppet.debug "Install: #{to_install.map {|p| "#{p[0]}-#{p[1]}" }. join ' '}" if to_install.any?
|
||||||
|
Puppet.debug "Remove: #{to_remove.map {|p| "#{p[0]}-#{p[1]}" }. join ' '}" if to_remove.any?
|
||||||
|
Puppet.debug "Update: #{to_update.map {|p| "#{p[0]}-#{p[1]}" }. join ' '}" if to_update.any?
|
||||||
|
to_install = to_install.merge to_update
|
||||||
|
yum_shell yum_options, operation, to_install, to_remove
|
||||||
|
elsif from.is_a?(String) && to.is_a?(String)
|
||||||
|
# update form one version to another
|
||||||
|
before, after = yum_with_changes yum_options, operation, wanted
|
||||||
|
diff = make_package_diff before, after
|
||||||
|
file_path = File.join @file_dir, "#{name}_#{from}_#{to}.yaml"
|
||||||
|
save_diff file_path, diff
|
||||||
|
Puppet.debug "Saving diff file to #{file_path}"
|
||||||
|
else
|
||||||
|
# just a simple install
|
||||||
|
output = yum "-d", "0", "-e", "0", "-y", operation, wanted
|
||||||
|
end
|
||||||
|
|
||||||
|
is = check_query
|
||||||
raise Puppet::Error, "Could not find package #{self.name}" unless is
|
raise Puppet::Error, "Could not find package #{self.name}" unless is
|
||||||
|
|
||||||
# FIXME: Should we raise an exception even if should == :latest
|
# FIXME: Should we raise an exception even if should == :latest
|
||||||
@ -84,6 +162,68 @@ Puppet::Type.type(:package).provide :yum, :parent => :rpm, :source => :rpm do
|
|||||||
raise Puppet::Error, "Failed to update to version #{should}, got version #{is[:ensure]} instead" if should && should != is[:ensure]
|
raise Puppet::Error, "Failed to update to version #{should}, got version #{is[:ensure]} instead" if should && should != is[:ensure]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# run the yum shell to install and remove packages
|
||||||
|
# @param options <Array[String]>
|
||||||
|
# @param operation <String,Symbol>
|
||||||
|
# @param to_install <Hash>
|
||||||
|
# @param to_remove <Hash>
|
||||||
|
def yum_shell(options, operation, to_install, to_remove)
|
||||||
|
tmp_file = '/tmp/yum.shell'
|
||||||
|
yum_shell = ''
|
||||||
|
yum_shell += "#{operation} #{to_install.map {|p| "#{p[0]}-#{p[1]}" }. join ' '}\n" if to_install.any?
|
||||||
|
yum_shell += "remove #{to_remove.map {|p| "#{p[0]}-#{p[1]}" }. join ' '}\n" if to_remove.any?
|
||||||
|
yum_shell += "run\n"
|
||||||
|
File.open(tmp_file, 'w') { |file| file.write yum_shell }
|
||||||
|
output = yum "--setopt", "obsoletes=0", options, 'shell', tmp_file
|
||||||
|
File.delete tmp_file
|
||||||
|
end
|
||||||
|
|
||||||
|
# package state query executed after the install to check its success
|
||||||
|
# separate method is made because it can be stubbed by the spec
|
||||||
|
# @return Hash
|
||||||
|
def check_query
|
||||||
|
self.query
|
||||||
|
end
|
||||||
|
|
||||||
|
# combine before and after lists into a diff
|
||||||
|
# @param before <Hash[String]>
|
||||||
|
# @param after <Hash[String]>
|
||||||
|
def make_package_diff(before, after)
|
||||||
|
installed = package_diff after, before
|
||||||
|
removed = package_diff before, after
|
||||||
|
{ 'installed' => installed, 'removed' => removed }
|
||||||
|
end
|
||||||
|
|
||||||
|
# run yum operation and get package
|
||||||
|
# lists before and after of it
|
||||||
|
# @param options <Array[String]>
|
||||||
|
# @param operation <String,Symbol>
|
||||||
|
# @param wanted <String>
|
||||||
|
def yum_with_changes(options, operation, wanted)
|
||||||
|
before = pkg_list
|
||||||
|
yum options, operation, wanted
|
||||||
|
after = pkg_list
|
||||||
|
[ before, after ]
|
||||||
|
end
|
||||||
|
|
||||||
|
# saves diff hash into a file
|
||||||
|
# @param file_path <String>
|
||||||
|
# @param diff <Hash[String]>
|
||||||
|
def save_diff(file_path, diff)
|
||||||
|
Dir.mkdir @file_dir unless File.directory? @file_dir
|
||||||
|
File.open(file_path, 'w') { |file| file.write YAML.dump(diff) + "\n" }
|
||||||
|
end
|
||||||
|
|
||||||
|
# reads diff hash from a file
|
||||||
|
# @param file_path <String>
|
||||||
|
# @returns <Hash[String]>
|
||||||
|
def read_diff(file_path)
|
||||||
|
return unless File.readable? file_path
|
||||||
|
diff = YAML.load_file file_path
|
||||||
|
return unless diff.is_a? Hash
|
||||||
|
diff
|
||||||
|
end
|
||||||
|
|
||||||
# What's the latest package version available?
|
# What's the latest package version available?
|
||||||
def latest
|
def latest
|
||||||
upd = latest_info
|
upd = latest_info
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
# systems.
|
# systems.
|
||||||
|
|
||||||
require 'puppet/parameter/package_options'
|
require 'puppet/parameter/package_options'
|
||||||
|
require 'yaml'
|
||||||
|
|
||||||
module Puppet
|
module Puppet
|
||||||
newtype(:package) do
|
newtype(:package) do
|
||||||
@ -116,6 +117,61 @@ module Puppet
|
|||||||
|
|
||||||
defaultto :installed
|
defaultto :installed
|
||||||
|
|
||||||
|
munge do |value|
|
||||||
|
#puts "VALUE #{value} CLASS #{value.class}"
|
||||||
|
value = value.to_sym if %w(present installed latest absent purged held).include? value
|
||||||
|
|
||||||
|
if value.is_a? FalseClass
|
||||||
|
:absent
|
||||||
|
elsif value.is_a? TrueClass
|
||||||
|
:installed
|
||||||
|
elsif value == :installed
|
||||||
|
:present
|
||||||
|
else
|
||||||
|
value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# lookup package version in versions file
|
||||||
|
# returns nil if version is not found
|
||||||
|
# @return <String,NilClass>
|
||||||
|
def lookup_version
|
||||||
|
package_name = @resource.name.to_s
|
||||||
|
|
||||||
|
versions_file = case @resource.provider.class.name
|
||||||
|
when :apt then '/etc/puppet/manifests/ubuntu-versions.yaml'
|
||||||
|
when :yum then '/etc/puppet/manifests/centos-versions.yaml'
|
||||||
|
else return
|
||||||
|
end
|
||||||
|
|
||||||
|
return unless File.readable? versions_file
|
||||||
|
versions = YAML.load_file versions_file
|
||||||
|
return unless versions.is_a? Hash
|
||||||
|
versions.dup.each do |k, v|
|
||||||
|
next if k.is_a? String
|
||||||
|
versions.delete k
|
||||||
|
versions.store k.to_s, v
|
||||||
|
end
|
||||||
|
return unless versions.key? package_name
|
||||||
|
version = versions[package_name].to_s
|
||||||
|
Puppet.debug "Got version '#{version}' for package '#{package_name}' from the versions file"
|
||||||
|
version
|
||||||
|
end
|
||||||
|
|
||||||
|
# modify @should Array if we want to lookup package version
|
||||||
|
# returns @should element without Array
|
||||||
|
# @return <String,Symbol>
|
||||||
|
def should
|
||||||
|
value = super
|
||||||
|
return value unless [:installed,:present].include? @should.first
|
||||||
|
version = lookup_version
|
||||||
|
if version
|
||||||
|
@should[0] = version
|
||||||
|
return version
|
||||||
|
end
|
||||||
|
value
|
||||||
|
end
|
||||||
|
|
||||||
# Override the parent method, because we've got all kinds of
|
# Override the parent method, because we've got all kinds of
|
||||||
# funky definitions of 'in sync'.
|
# funky definitions of 'in sync'.
|
||||||
def insync?(is)
|
def insync?(is)
|
||||||
|
1
deployment/puppet/package/spec/spec_helper.rb
Normal file
1
deployment/puppet/package/spec/spec_helper.rb
Normal file
@ -0,0 +1 @@
|
|||||||
|
require 'puppetlabs_spec_helper/module_spec_helper'
|
245
deployment/puppet/package/spec/unit/provider/package/apt_spec.rb
Executable file
245
deployment/puppet/package/spec/unit/provider/package/apt_spec.rb
Executable file
@ -0,0 +1,245 @@
|
|||||||
|
#! /usr/bin/env ruby
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
provider = Puppet::Type.type(:package).provider(:apt)
|
||||||
|
|
||||||
|
describe provider do
|
||||||
|
before do
|
||||||
|
@resource = stub 'resource', :[] => "asdf"
|
||||||
|
@provider = provider.new(@resource)
|
||||||
|
|
||||||
|
@fakeresult = <<-EOF
|
||||||
|
install ok installed asdf 1.0 "asdf summary
|
||||||
|
asdf multiline description
|
||||||
|
with multiple lines
|
||||||
|
EOF
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should be versionable" do
|
||||||
|
provider.should be_versionable
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should use :install to update" do
|
||||||
|
@provider.expects(:install)
|
||||||
|
@provider.update
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should use 'apt-get remove' to uninstall" do
|
||||||
|
@provider.expects(:aptget).with("-y", "-q", :remove, "asdf")
|
||||||
|
|
||||||
|
@provider.uninstall
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should use 'apt-get purge' and 'dpkg purge' to purge" do
|
||||||
|
@provider.expects(:aptget).with("-y", "-q", :remove, "--purge", "asdf")
|
||||||
|
@provider.expects(:dpkg).with("--purge", "asdf")
|
||||||
|
|
||||||
|
@provider.purge
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should use 'apt-cache policy' to determine the latest version of a package" do
|
||||||
|
@provider.expects(:aptcache).with(:policy, "asdf").returns "asdf:
|
||||||
|
Installed: 1:1.0
|
||||||
|
Candidate: 1:1.1
|
||||||
|
Version table:
|
||||||
|
1:1.0
|
||||||
|
650 http://ftp.osuosl.org testing/main Packages
|
||||||
|
*** 1:1.1
|
||||||
|
100 /var/lib/dpkg/status"
|
||||||
|
|
||||||
|
@provider.latest.should == "1:1.1"
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should print and error and return nil if no policy is found" do
|
||||||
|
@provider.expects(:aptcache).with(:policy, "asdf").returns "asdf:"
|
||||||
|
|
||||||
|
@provider.expects(:err)
|
||||||
|
@provider.latest.should be_nil
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should be able to preseed" do
|
||||||
|
@provider.should respond_to(:run_preseed)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should preseed with the provided responsefile when preseeding is called for" do
|
||||||
|
@resource.expects(:[]).with(:responsefile).returns "/my/file"
|
||||||
|
Puppet::FileSystem::File.expects(:exist?).with("/my/file").returns true
|
||||||
|
|
||||||
|
@provider.expects(:info)
|
||||||
|
@provider.expects(:preseed).with("/my/file")
|
||||||
|
|
||||||
|
@provider.run_preseed
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should not preseed if no responsefile is provided" do
|
||||||
|
@resource.expects(:[]).with(:responsefile).returns nil
|
||||||
|
|
||||||
|
@provider.expects(:info)
|
||||||
|
@provider.expects(:preseed).never
|
||||||
|
|
||||||
|
@provider.run_preseed
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "when installing" do
|
||||||
|
it "should preseed if a responsefile is provided" do
|
||||||
|
@resource.expects(:[]).with(:responsefile).returns "/my/file"
|
||||||
|
@provider.expects(:run_preseed)
|
||||||
|
|
||||||
|
@provider.stubs(:aptget)
|
||||||
|
@provider.install
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should check for a cdrom" do
|
||||||
|
@provider.expects(:checkforcdrom)
|
||||||
|
|
||||||
|
@provider.stubs(:aptget)
|
||||||
|
@provider.install
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should use 'apt-get install' with the package name if no version is asked for" do
|
||||||
|
@resource.expects(:[]).with(:ensure).returns :installed
|
||||||
|
@provider.expects(:aptget).with { |*command| command[-1] == "asdf" and command[-2] == :install }
|
||||||
|
|
||||||
|
@provider.install
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should specify the package version if one is asked for" do
|
||||||
|
@resource.expects(:[]).with(:ensure).returns "1.0"
|
||||||
|
@provider.expects(:aptget).with { |*command| command[-1] == "asdf=1.0" }
|
||||||
|
|
||||||
|
@provider.install
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should use --force-yes if a package version is specified" do
|
||||||
|
@resource.expects(:[]).with(:ensure).returns "1.0"
|
||||||
|
@provider.expects(:aptget).with { |*command| command.include?("--force-yes") }
|
||||||
|
|
||||||
|
@provider.install
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should do a quiet install" do
|
||||||
|
@provider.expects(:aptget).with { |*command| command.include?("-q") }
|
||||||
|
|
||||||
|
@provider.install
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should default to 'yes' for all questions" do
|
||||||
|
@provider.expects(:aptget).with { |*command| command.include?("-y") }
|
||||||
|
|
||||||
|
@provider.install
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should keep config files if asked" do
|
||||||
|
@resource.expects(:[]).with(:configfiles).returns :keep
|
||||||
|
@provider.expects(:aptget).with { |*command| command.include?("DPkg::Options::=--force-confold") }
|
||||||
|
|
||||||
|
@provider.install
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should replace config files if asked" do
|
||||||
|
@resource.expects(:[]).with(:configfiles).returns :replace
|
||||||
|
@provider.expects(:aptget).with { |*command| command.include?("DPkg::Options::=--force-confnew") }
|
||||||
|
|
||||||
|
@provider.install
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "with transactional rollback support" do
|
||||||
|
|
||||||
|
let(:file_dir) { '/var/lib/puppet/rollback' }
|
||||||
|
let(:rollback_file_up) { '/var/lib/puppet/rollback/asdf_1.0_2.0.yaml' }
|
||||||
|
let(:rollback_file_down) { '/var/lib/puppet/rollback/asdf_2.0_1.0.yaml' }
|
||||||
|
|
||||||
|
let(:before) do
|
||||||
|
{
|
||||||
|
'otherpkg' => '1',
|
||||||
|
'asdf' => '1.0',
|
||||||
|
'asdf-lib' => '1.0',
|
||||||
|
'asdf-old-dep' => '1',
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:after) do
|
||||||
|
{
|
||||||
|
'otherpkg' => '1',
|
||||||
|
'asdf' => '2.0',
|
||||||
|
'asdf-lib' => '2.0',
|
||||||
|
'asdf-new-dep' => '1',
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:diff) do
|
||||||
|
{
|
||||||
|
'installed' => {
|
||||||
|
'asdf' => '2.0',
|
||||||
|
'asdf-lib' => '2.0',
|
||||||
|
'asdf-new-dep' => '1'
|
||||||
|
},
|
||||||
|
'removed' => {
|
||||||
|
'asdf' => '1.0',
|
||||||
|
'asdf-lib' => '1.0',
|
||||||
|
'asdf-old-dep' => '1'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:pkgs) { [ 'asdf=1.0', 'asdf-lib=1.0', 'asdf-old-dep=1', 'asdf-new-dep-' ] }
|
||||||
|
|
||||||
|
after(:each) do
|
||||||
|
@provider.properties
|
||||||
|
@provider.install
|
||||||
|
end
|
||||||
|
|
||||||
|
before(:each) do
|
||||||
|
File.stubs(:directory?).with(file_dir).returns true
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "when updating" do
|
||||||
|
before(:each) do
|
||||||
|
@provider.stubs(:read_diff).returns nil
|
||||||
|
end
|
||||||
|
|
||||||
|
it "saves diff only when version is changing and there is no rollback file" do
|
||||||
|
@resource.stubs(:[]).with(:ensure).returns "2.0"
|
||||||
|
@provider.stubs(:query).returns({:ensure => '1.0', :status => '1.0', :name => 'asdf', :error => 'ok'})
|
||||||
|
@provider.stubs(:read_diff).with(rollback_file_down).returns nil
|
||||||
|
@provider.stubs(:aptget_with_changes).with { |command| command[-1] == "asdf=2.0" }
|
||||||
|
@provider.stubs(:make_package_diff).times(1)
|
||||||
|
@provider.stubs(:save_diff).times(1)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "doesn't save diff when package is being installed the first time" do
|
||||||
|
@resource.stubs(:[]).with(:ensure).returns :present
|
||||||
|
@provider.stubs(:query).returns({:ensure => :absent, :status => 'missing', :name => 'asdf', :error => 'ok'})
|
||||||
|
@provider.stubs(:aptget).with { |*command| command[-1] == "asdf" }
|
||||||
|
@provider.stubs(:save_diff).times(0)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "saves correct diff to the rollback file" do
|
||||||
|
@resource.stubs(:[]).with(:ensure).returns "2.0"
|
||||||
|
@provider.stubs(:query).returns({:ensure => '1.0', :status => '1.0', :name => 'asdf', :error => 'ok'})
|
||||||
|
@provider.stubs(:aptget_with_changes).with { |command| command[-1] == "asdf=2.0" }.returns([before, after])
|
||||||
|
@provider.stubs(:save_diff).with(rollback_file_up, diff)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "when rolling back" do
|
||||||
|
it 'only when rollback file is found' do
|
||||||
|
@resource.stubs(:[]).with(:ensure).returns "1.0"
|
||||||
|
@provider.stubs(:query).returns({:ensure => '2.0', :status => '2.0', :name => 'asdf', :error => 'ok'})
|
||||||
|
@provider.stubs(:read_diff).with(rollback_file_up).returns nil
|
||||||
|
@provider.stubs(:aptget).with { |*command| command[-2,2] == [:install, 'asdf=1.0'] }
|
||||||
|
@provider.stubs(:save_diff).times(1)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "calls apt-get with correct package list" do
|
||||||
|
@resource.stubs(:[]).with(:ensure).returns "1.0"
|
||||||
|
@provider.stubs(:query).returns({:ensure => '2.0', :status => '1.0', :name => 'asdf', :error => 'ok'})
|
||||||
|
@provider.stubs(:read_diff).with(rollback_file_up).returns(diff)
|
||||||
|
@provider.stubs(:aptget).with { |*command| command[-5,5] == [ :install ] + pkgs }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
296
deployment/puppet/package/spec/unit/provider/package/yum_spec.rb
Executable file
296
deployment/puppet/package/spec/unit/provider/package/yum_spec.rb
Executable file
@ -0,0 +1,296 @@
|
|||||||
|
#! /usr/bin/env ruby
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
provider = Puppet::Type.type(:package).provider(:yum)
|
||||||
|
|
||||||
|
describe provider do
|
||||||
|
before do
|
||||||
|
# Create a mock resource
|
||||||
|
@resource = stub 'resource'
|
||||||
|
@resource.stubs(:[]).with(:name).returns 'mypackage'
|
||||||
|
@provider = provider.new(@resource)
|
||||||
|
@provider.stubs(:resource).returns @resource
|
||||||
|
@provider.stubs(:yum).returns 'yum'
|
||||||
|
@provider.stubs(:rpm).returns 'rpm'
|
||||||
|
@provider.stubs(:get).with(:name).returns 'mypackage'
|
||||||
|
@provider.stubs(:get).with(:version).returns '1'
|
||||||
|
@provider.stubs(:get).with(:release).returns '1'
|
||||||
|
@provider.stubs(:get).with(:arch).returns 'i386'
|
||||||
|
end
|
||||||
|
# provider should repond to the following methods
|
||||||
|
[:install, :latest, :update, :purge].each do |method|
|
||||||
|
it "should have a(n) #{method}" do
|
||||||
|
@provider.should respond_to(method)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'when installing' do
|
||||||
|
before(:each) do
|
||||||
|
Puppet::Util.stubs(:which).with("rpm").returns("/bin/rpm")
|
||||||
|
provider.stubs(:which).with("rpm").returns("/bin/rpm")
|
||||||
|
Puppet::Util::Execution.expects(:execute).with(["/bin/rpm", "--version"], {:combine => true, :custom_environment => {}, :failonfail => true}).returns("4.10.1\n").at_most_once
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should call yum install for :installed' do
|
||||||
|
@resource.stubs(:should).with(:ensure).returns :installed
|
||||||
|
@provider.expects(:yum).with('-d', '0', '-e', '0', '-y', :install, 'mypackage')
|
||||||
|
@provider.install
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should use :install to update' do
|
||||||
|
@provider.expects(:install)
|
||||||
|
@provider.update
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should be able to set version' do
|
||||||
|
@resource.stubs(:should).with(:ensure).returns '1.2'
|
||||||
|
@provider.expects(:yum).with('-d', '0', '-e', '0', '-y', :install, 'mypackage-1.2')
|
||||||
|
@provider.stubs(:query).returns :ensure => '1.2'
|
||||||
|
@provider.install
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should be able to downgrade' do
|
||||||
|
@resource.stubs(:should).with(:ensure).returns '1.0'
|
||||||
|
@provider.expects(:yum).with('-d', '0', '-e', '0', '-y', :downgrade, 'mypackage-1.0')
|
||||||
|
@provider.stubs(:query).returns(:ensure => '1.2').then.returns(:ensure => '1.0')
|
||||||
|
@provider.install
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'when uninstalling' do
|
||||||
|
it 'should use erase to purge' do
|
||||||
|
@provider.expects(:yum).with('-y', :erase, 'mypackage')
|
||||||
|
@provider.purge
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should be versionable' do
|
||||||
|
provider.should be_versionable
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#latest' do
|
||||||
|
describe 'when latest_info is nil' do
|
||||||
|
before :each do
|
||||||
|
@provider.stubs(:latest_info).returns(nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'raises if ensure is absent and latest_info is nil' do
|
||||||
|
@provider.stubs(:properties).returns({:ensure => :absent})
|
||||||
|
|
||||||
|
expect { @provider.latest }.to raise_error(
|
||||||
|
Puppet::DevError,
|
||||||
|
'Tried to get latest on a missing package'
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns the ensure value if the package is not already installed' do
|
||||||
|
@provider.stubs(:properties).returns({:ensure => '3.4.5'})
|
||||||
|
|
||||||
|
@provider.latest.should == '3.4.5'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'when latest_info is populated' do
|
||||||
|
before :each do
|
||||||
|
@provider.stubs(:latest_info).returns({
|
||||||
|
:name => 'mypackage',
|
||||||
|
:epoch => '1',
|
||||||
|
:version => '2.3.4',
|
||||||
|
:release => '5',
|
||||||
|
:arch => 'i686',
|
||||||
|
:provider => :yum,
|
||||||
|
:ensure => '2.3.4-5'
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'includes the epoch in the version string' do
|
||||||
|
@provider.latest.should == '1:2.3.4-5'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'prefetching' do
|
||||||
|
let(:nevra_format) { Puppet::Type::Package::ProviderRpm::NEVRA_FORMAT }
|
||||||
|
|
||||||
|
let(:packages) do
|
||||||
|
<<-RPM_OUTPUT
|
||||||
|
cracklib-dicts 0 2.8.9 3.3 x86_64 :DESC: The standard CrackLib dictionaries
|
||||||
|
basesystem 0 8.0 5.1.1.el5.centos noarch :DESC: The skeleton package which defines a simple Red Hat Enterprise Linux system
|
||||||
|
chkconfig 0 1.3.30.2 2.el5 x86_64 :DESC: A system tool for maintaining the /etc/rc*.d hierarchy
|
||||||
|
myresource 0 1.2.3.4 5.el4 noarch :DESC: Now with summary
|
||||||
|
mysummaryless 0 1.2.3.4 5.el4 noarch :DESC:
|
||||||
|
RPM_OUTPUT
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:yumhelper_output) do
|
||||||
|
<<-YUMHELPER_OUTPUT
|
||||||
|
* base: centos.tcpdiag.net
|
||||||
|
* extras: centos.mirrors.hoobly.com
|
||||||
|
* updates: mirrors.arsc.edu
|
||||||
|
_pkg nss-tools 0 3.14.3 4.el6_4 x86_64
|
||||||
|
_pkg pixman 0 0.26.2 5.el6_4 x86_64
|
||||||
|
_pkg myresource 0 1.2.3.4 5.el4 noarch
|
||||||
|
_pkg mysummaryless 0 1.2.3.4 5.el4 noarch
|
||||||
|
YUMHELPER_OUTPUT
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:execute_options) do
|
||||||
|
{:failonfail => true, :combine => true, :custom_environment => {}}
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:rpm_version) { "RPM version 4.8.0\n" }
|
||||||
|
|
||||||
|
let(:package_type) { Puppet::Type.type(:package) }
|
||||||
|
let(:yum_provider) { provider }
|
||||||
|
|
||||||
|
def pretend_we_are_root_for_yum_provider
|
||||||
|
Process.stubs(:euid).returns(0)
|
||||||
|
end
|
||||||
|
|
||||||
|
def expect_yum_provider_to_provide_rpm
|
||||||
|
Puppet::Type::Package::ProviderYum.stubs(:rpm).with('--version').returns(rpm_version)
|
||||||
|
Puppet::Type::Package::ProviderYum.expects(:command).with(:rpm).returns("/bin/rpm")
|
||||||
|
end
|
||||||
|
|
||||||
|
def expect_execpipe_to_provide_package_info_for_an_rpm_query
|
||||||
|
Puppet::Util::Execution.expects(:execpipe).with("/bin/rpm -qa --nosignature --nodigest --qf '#{nevra_format}'").yields(packages)
|
||||||
|
end
|
||||||
|
|
||||||
|
def expect_python_yumhelper_call_to_return_latest_info
|
||||||
|
Puppet::Type::Package::ProviderYum.expects(:python).with(regexp_matches(/yumhelper.py$/)).returns(yumhelper_output)
|
||||||
|
end
|
||||||
|
|
||||||
|
def a_package_type_instance_with_yum_provider_and_ensure_latest(name)
|
||||||
|
type_instance = package_type.new(:name => name)
|
||||||
|
type_instance.provider = yum_provider.new
|
||||||
|
type_instance[:ensure] = :latest
|
||||||
|
return type_instance
|
||||||
|
end
|
||||||
|
|
||||||
|
before do
|
||||||
|
pretend_we_are_root_for_yum_provider
|
||||||
|
expect_yum_provider_to_provide_rpm
|
||||||
|
expect_execpipe_to_provide_package_info_for_an_rpm_query
|
||||||
|
expect_python_yumhelper_call_to_return_latest_info
|
||||||
|
end
|
||||||
|
|
||||||
|
it "injects latest provider info into passed resources when prefetching" do
|
||||||
|
myresource = a_package_type_instance_with_yum_provider_and_ensure_latest('myresource')
|
||||||
|
mysummaryless = a_package_type_instance_with_yum_provider_and_ensure_latest('mysummaryless')
|
||||||
|
|
||||||
|
yum_provider.prefetch({ "myresource" => myresource, "mysummaryless" => mysummaryless })
|
||||||
|
|
||||||
|
expect(@logs.map(&:message).grep(/^Failed to match rpm line/)).to be_empty
|
||||||
|
expect(myresource.provider.latest_info).to eq({
|
||||||
|
:name=>"myresource",
|
||||||
|
:epoch=>"0",
|
||||||
|
:version=>"1.2.3.4",
|
||||||
|
:release=>"5.el4",
|
||||||
|
:arch=>"noarch",
|
||||||
|
:provider=>:yum,
|
||||||
|
:ensure=>"1.2.3.4-5.el4"
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "with transactional rollback support" do
|
||||||
|
let(:yum_options) { %w(-d 0 -e 0 -y) }
|
||||||
|
let(:file_dir) { '/var/lib/puppet/rollback' }
|
||||||
|
let(:rollback_file_down) { '/var/lib/puppet/rollback/mypackage_2.0_1.0.yaml' }
|
||||||
|
let(:rollback_file_up) { '/var/lib/puppet/rollback/mypackage_1.0_2.0.yaml' }
|
||||||
|
|
||||||
|
let(:before) do
|
||||||
|
{
|
||||||
|
'otherpkg' => '1',
|
||||||
|
'asdf' => '1.0',
|
||||||
|
'asdf-lib' => '1.0',
|
||||||
|
'asdf-old-dep' => '1',
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
let (:after) do
|
||||||
|
{
|
||||||
|
'otherpkg' => '1',
|
||||||
|
'asdf' => '2.0',
|
||||||
|
'asdf-lib' => '2.0',
|
||||||
|
'asdf-new-dep' => '1',
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
let (:diff) do
|
||||||
|
{
|
||||||
|
'installed' => {
|
||||||
|
'asdf' => '2.0',
|
||||||
|
'asdf-lib' => '2.0',
|
||||||
|
'asdf-new-dep' => '1'
|
||||||
|
},
|
||||||
|
'removed' => {
|
||||||
|
'asdf' => '1.0',
|
||||||
|
'asdf-lib' => '1.0',
|
||||||
|
'asdf-old-dep' => '1'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
after(:each) do
|
||||||
|
@provider.properties
|
||||||
|
@provider.install
|
||||||
|
end
|
||||||
|
|
||||||
|
before(:each) do
|
||||||
|
File.stubs(:directory?).with(file_dir).returns true
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "when updating" do
|
||||||
|
before(:each) {
|
||||||
|
@provider.stubs(:read_diff).returns nil
|
||||||
|
}
|
||||||
|
|
||||||
|
it "saves diff only when version is changing and there is no rollback file" do
|
||||||
|
@resource.stubs(:should).with(:ensure).returns '2.0'
|
||||||
|
@provider.stubs(:query).returns(:ensure => '1.0')
|
||||||
|
@provider.stubs(:check_query).returns(:ensure => '2.0')
|
||||||
|
@provider.stubs(:yum_with_changes).with(yum_options, :install, 'mypackage-2.0')
|
||||||
|
@provider.stubs(:make_package_diff).times(1)
|
||||||
|
@provider.stubs(:save_diff).times(1)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "doesn't save diff when package is being installed the first time" do
|
||||||
|
@resource.stubs(:should).with(:ensure).returns :present
|
||||||
|
@provider.stubs(:query).returns(:ensure => :absent)
|
||||||
|
@provider.stubs(:yum).with(*yum_options, :install, 'mypackage')
|
||||||
|
@provider.stubs(:save_diff).times(0)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "saves correct diff to the rollback file" do
|
||||||
|
@resource.stubs(:should).with(:ensure).returns '2.0'
|
||||||
|
@provider.stubs(:query).returns(:ensure => '1.0')
|
||||||
|
@provider.stubs(:check_query).returns(:ensure => '2.0')
|
||||||
|
@provider.stubs(:yum_with_changes).with(yum_options, :install, 'mypackage-2.0').returns([before, after])
|
||||||
|
@provider.stubs(:save_diff).with(rollback_file_up, diff)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "when rolling back" do
|
||||||
|
it 'only when rollback file is found' do
|
||||||
|
@resource.stubs(:should).with(:ensure).returns '1.0'
|
||||||
|
@provider.stubs(:query).returns(:ensure => '2.0')
|
||||||
|
@provider.stubs(:check_query).returns(:ensure => '1.0')
|
||||||
|
@provider.stubs(:read_diff).with(rollback_file_up).returns nil
|
||||||
|
@provider.stubs(:yum).with(*yum_options, :downgrade, 'mypackage-1.0')
|
||||||
|
@provider.stubs(:save_diff).times(1)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "calls apt-get with correct package list" do
|
||||||
|
@resource.stubs(:should).with(:ensure).returns '1.0'
|
||||||
|
@provider.stubs(:query).returns(:ensure => '2.0')
|
||||||
|
@provider.stubs(:check_query).returns(:ensure => '1.0')
|
||||||
|
@provider.stubs(:read_diff).with(rollback_file_up).returns diff
|
||||||
|
@provider.stubs(:yum_shell).times(1)
|
||||||
|
@provider.stubs(:save_diff).times(0)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
386
deployment/puppet/package/spec/unit/type/package_spec.rb
Executable file
386
deployment/puppet/package/spec/unit/type/package_spec.rb
Executable file
@ -0,0 +1,386 @@
|
|||||||
|
#! /usr/bin/env ruby
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
describe Puppet::Type.type(:package) do
|
||||||
|
before do
|
||||||
|
Puppet::Util::Storage.stubs(:store)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should have an :installable feature that requires the :install method" do
|
||||||
|
Puppet::Type.type(:package).provider_feature(:installable).methods.should == [:install]
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should have an :uninstallable feature that requires the :uninstall method" do
|
||||||
|
Puppet::Type.type(:package).provider_feature(:uninstallable).methods.should == [:uninstall]
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should have an :upgradeable feature that requires :update and :latest methods" do
|
||||||
|
Puppet::Type.type(:package).provider_feature(:upgradeable).methods.should == [:update, :latest]
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should have a :purgeable feature that requires the :purge latest method" do
|
||||||
|
Puppet::Type.type(:package).provider_feature(:purgeable).methods.should == [:purge]
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should have a :versionable feature" do
|
||||||
|
Puppet::Type.type(:package).provider_feature(:versionable).should_not be_nil
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should default to being installed" do
|
||||||
|
pkg = Puppet::Type.type(:package).new(:name => "yay", :provider => :apt)
|
||||||
|
pkg.should(:ensure).should == :present
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "when validating attributes" do
|
||||||
|
[:name, :source, :instance, :status, :adminfile, :responsefile, :configfiles, :category, :platform, :root, :vendor, :description, :allowcdrom].each do |param|
|
||||||
|
it "should have a #{param} parameter" do
|
||||||
|
Puppet::Type.type(:package).attrtype(param).should == :param
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should have an ensure property" do
|
||||||
|
Puppet::Type.type(:package).attrtype(:ensure).should == :property
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "when validating attribute values" do
|
||||||
|
before do
|
||||||
|
@provider = stub(
|
||||||
|
'provider',
|
||||||
|
:class => Puppet::Type.type(:package).defaultprovider,
|
||||||
|
:clear => nil,
|
||||||
|
:validate_source => nil
|
||||||
|
)
|
||||||
|
Puppet::Type.type(:package).defaultprovider.stubs(:new).returns(@provider)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should support :present as a value to :ensure" do
|
||||||
|
Puppet::Type.type(:package).new(:name => "yay", :ensure => :present)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should alias :installed to :present as a value to :ensure" do
|
||||||
|
pkg = Puppet::Type.type(:package).new(:name => "yay", :ensure => :installed)
|
||||||
|
pkg.should(:ensure).should == :present
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should support :absent as a value to :ensure" do
|
||||||
|
Puppet::Type.type(:package).new(:name => "yay", :ensure => :absent)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should support :purged as a value to :ensure if the provider has the :purgeable feature" do
|
||||||
|
@provider.expects(:satisfies?).with([:purgeable]).returns(true)
|
||||||
|
Puppet::Type.type(:package).new(:name => "yay", :ensure => :purged)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should not support :purged as a value to :ensure if the provider does not have the :purgeable feature" do
|
||||||
|
@provider.expects(:satisfies?).with([:purgeable]).returns(false)
|
||||||
|
expect { Puppet::Type.type(:package).new(:name => "yay", :ensure => :purged) }.to raise_error(Puppet::Error)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should support :latest as a value to :ensure if the provider has the :upgradeable feature" do
|
||||||
|
@provider.expects(:satisfies?).with([:upgradeable]).returns(true)
|
||||||
|
Puppet::Type.type(:package).new(:name => "yay", :ensure => :latest)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should not support :latest as a value to :ensure if the provider does not have the :upgradeable feature" do
|
||||||
|
@provider.expects(:satisfies?).with([:upgradeable]).returns(false)
|
||||||
|
expect { Puppet::Type.type(:package).new(:name => "yay", :ensure => :latest) }.to raise_error(Puppet::Error)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should support version numbers as a value to :ensure if the provider has the :versionable feature" do
|
||||||
|
@provider.expects(:satisfies?).with([:versionable]).returns(true)
|
||||||
|
Puppet::Type.type(:package).new(:name => "yay", :ensure => "1.0")
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should not support version numbers as a value to :ensure if the provider does not have the :versionable feature" do
|
||||||
|
@provider.expects(:satisfies?).with([:versionable]).returns(false)
|
||||||
|
expect { Puppet::Type.type(:package).new(:name => "yay", :ensure => "1.0") }.to raise_error(Puppet::Error)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should accept any string as an argument to :source" do
|
||||||
|
expect { Puppet::Type.type(:package).new(:name => "yay", :source => "stuff") }.to_not raise_error
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should not accept a non-string name" do
|
||||||
|
expect do
|
||||||
|
Puppet::Type.type(:package).new(:name => ["error"])
|
||||||
|
end.to raise_error(Puppet::ResourceError, /Name must be a String/)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
module PackageEvaluationTesting
|
||||||
|
def setprops(properties)
|
||||||
|
@provider.stubs(:properties).returns(properties)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe Puppet::Type.type(:package) do
|
||||||
|
before :each do
|
||||||
|
@provider = stub(
|
||||||
|
'provider',
|
||||||
|
:class => Puppet::Type.type(:package).defaultprovider,
|
||||||
|
:clear => nil,
|
||||||
|
:satisfies? => true,
|
||||||
|
:name => :mock,
|
||||||
|
:validate_source => nil
|
||||||
|
)
|
||||||
|
Puppet::Type.type(:package).defaultprovider.stubs(:new).returns(@provider)
|
||||||
|
Puppet::Type.type(:package).defaultprovider.stubs(:instances).returns([])
|
||||||
|
@package = Puppet::Type.type(:package).new(:name => "yay")
|
||||||
|
|
||||||
|
@catalog = Puppet::Resource::Catalog.new
|
||||||
|
@catalog.add_resource(@package)
|
||||||
|
end
|
||||||
|
|
||||||
|
describe Puppet::Type.type(:package), "when it should be purged" do
|
||||||
|
include PackageEvaluationTesting
|
||||||
|
|
||||||
|
before { @package[:ensure] = :purged }
|
||||||
|
|
||||||
|
it "should do nothing if it is :purged" do
|
||||||
|
@provider.expects(:properties).returns(:ensure => :purged).at_least_once
|
||||||
|
@catalog.apply
|
||||||
|
end
|
||||||
|
|
||||||
|
[:absent, :installed, :present, :latest].each do |state|
|
||||||
|
it "should purge if it is #{state.to_s}" do
|
||||||
|
@provider.stubs(:properties).returns(:ensure => state)
|
||||||
|
@provider.expects(:purge)
|
||||||
|
@catalog.apply
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe Puppet::Type.type(:package), "when it should be absent" do
|
||||||
|
include PackageEvaluationTesting
|
||||||
|
|
||||||
|
before { @package[:ensure] = :absent }
|
||||||
|
|
||||||
|
[:purged, :absent].each do |state|
|
||||||
|
it "should do nothing if it is #{state.to_s}" do
|
||||||
|
@provider.expects(:properties).returns(:ensure => state).at_least_once
|
||||||
|
@catalog.apply
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
[:installed, :present, :latest].each do |state|
|
||||||
|
it "should uninstall if it is #{state.to_s}" do
|
||||||
|
@provider.stubs(:properties).returns(:ensure => state)
|
||||||
|
@provider.expects(:uninstall)
|
||||||
|
@catalog.apply
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe Puppet::Type.type(:package), "when it should be present" do
|
||||||
|
include PackageEvaluationTesting
|
||||||
|
|
||||||
|
before { @package[:ensure] = :present }
|
||||||
|
|
||||||
|
[:present, :latest, "1.0"].each do |state|
|
||||||
|
it "should do nothing if it is #{state.to_s}" do
|
||||||
|
@provider.expects(:properties).returns(:ensure => state).at_least_once
|
||||||
|
@catalog.apply
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
[:purged, :absent].each do |state|
|
||||||
|
it "should install if it is #{state.to_s}" do
|
||||||
|
@provider.stubs(:properties).returns(:ensure => state)
|
||||||
|
@provider.expects(:install)
|
||||||
|
@catalog.apply
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe Puppet::Type.type(:package), "when it should be latest" do
|
||||||
|
include PackageEvaluationTesting
|
||||||
|
|
||||||
|
before { @package[:ensure] = :latest }
|
||||||
|
|
||||||
|
[:purged, :absent].each do |state|
|
||||||
|
it "should upgrade if it is #{state.to_s}" do
|
||||||
|
@provider.stubs(:properties).returns(:ensure => state)
|
||||||
|
@provider.expects(:update)
|
||||||
|
@catalog.apply
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should upgrade if the current version is not equal to the latest version" do
|
||||||
|
@provider.stubs(:properties).returns(:ensure => "1.0")
|
||||||
|
@provider.stubs(:latest).returns("2.0")
|
||||||
|
@provider.expects(:update)
|
||||||
|
@catalog.apply
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should do nothing if it is equal to the latest version" do
|
||||||
|
@provider.stubs(:properties).returns(:ensure => "1.0")
|
||||||
|
@provider.stubs(:latest).returns("1.0")
|
||||||
|
@provider.expects(:update).never
|
||||||
|
@catalog.apply
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should do nothing if the provider returns :present as the latest version" do
|
||||||
|
@provider.stubs(:properties).returns(:ensure => :present)
|
||||||
|
@provider.stubs(:latest).returns("1.0")
|
||||||
|
@provider.expects(:update).never
|
||||||
|
@catalog.apply
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe Puppet::Type.type(:package), "when it should be a specific version" do
|
||||||
|
include PackageEvaluationTesting
|
||||||
|
|
||||||
|
before { @package[:ensure] = "1.0" }
|
||||||
|
|
||||||
|
[:purged, :absent].each do |state|
|
||||||
|
it "should install if it is #{state.to_s}" do
|
||||||
|
@provider.stubs(:properties).returns(:ensure => state)
|
||||||
|
@package.property(:ensure).insync?(state).should be_false
|
||||||
|
@provider.expects(:install)
|
||||||
|
@catalog.apply
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should do nothing if the current version is equal to the desired version" do
|
||||||
|
@provider.stubs(:properties).returns(:ensure => "1.0")
|
||||||
|
@package.property(:ensure).insync?('1.0').should be_true
|
||||||
|
@provider.expects(:install).never
|
||||||
|
@catalog.apply
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should install if the current version is not equal to the specified version" do
|
||||||
|
@provider.stubs(:properties).returns(:ensure => "2.0")
|
||||||
|
@package.property(:ensure).insync?('2.0').should be_false
|
||||||
|
@provider.expects(:install)
|
||||||
|
@catalog.apply
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "when current value is an array" do
|
||||||
|
let(:installed_versions) { ["1.0", "2.0", "3.0"] }
|
||||||
|
|
||||||
|
before (:each) do
|
||||||
|
@provider.stubs(:properties).returns(:ensure => installed_versions)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should install if value not in the array" do
|
||||||
|
@package[:ensure] = "1.5"
|
||||||
|
@package.property(:ensure).insync?(installed_versions).should be_false
|
||||||
|
@provider.expects(:install)
|
||||||
|
@catalog.apply
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should not install if value is in the array" do
|
||||||
|
@package[:ensure] = "2.0"
|
||||||
|
@package.property(:ensure).insync?(installed_versions).should be_true
|
||||||
|
@provider.expects(:install).never
|
||||||
|
@catalog.apply
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "when ensure is set to 'latest'" do
|
||||||
|
it "should not install if the value is in the array" do
|
||||||
|
@provider.expects(:latest).returns("3.0")
|
||||||
|
@package[:ensure] = "latest"
|
||||||
|
@package.property(:ensure).insync?(installed_versions).should be_true
|
||||||
|
@provider.expects(:install).never
|
||||||
|
@catalog.apply
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe Puppet::Type.type(:package), "with package version override" do
|
||||||
|
let(:ubuntu_file) {'/etc/puppet/manifests/ubuntu-versions.yaml'}
|
||||||
|
let(:centos_file) {'/etc/puppet/manifests/centos-versions.yaml'}
|
||||||
|
let(:file_content) do
|
||||||
|
file_content = {
|
||||||
|
'pkg_with_version' => '1',
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
before (:each) do
|
||||||
|
require 'yaml'
|
||||||
|
end
|
||||||
|
|
||||||
|
it "takes a version from the file with yum provider" do
|
||||||
|
File.stubs(:readable?).with(centos_file).returns true
|
||||||
|
YAML.stubs(:load_file).with(centos_file).returns file_content
|
||||||
|
pkg = Puppet::Type.type(:package).new(:name => "pkg_with_version", :ensure => :installed)
|
||||||
|
pkg.provider.class.stubs(:name).returns :yum
|
||||||
|
expect(pkg[:ensure]).to eq '1'
|
||||||
|
end
|
||||||
|
it "takes a version from the file with apt provider" do
|
||||||
|
File.stubs(:readable?).with(ubuntu_file).returns true
|
||||||
|
YAML.stubs(:load_file).with(ubuntu_file).returns file_content
|
||||||
|
pkg = Puppet::Type.type(:package).new(:name => "pkg_with_version", :ensure => :installed)
|
||||||
|
pkg.provider.class.stubs(:name).returns :apt
|
||||||
|
expect(pkg[:ensure]).to eq '1'
|
||||||
|
end
|
||||||
|
it "takes a version from the file with symbols and numbers" do
|
||||||
|
File.stubs(:readable?).with(centos_file).returns true
|
||||||
|
YAML.stubs(:load_file).with(centos_file).returns file_content
|
||||||
|
pkg = Puppet::Type.type(:package).new(:name => "pkg_with_version", :ensure => :installed)
|
||||||
|
pkg.provider.class.stubs(:name).returns :yum
|
||||||
|
expect(pkg[:ensure]).to eq '1'
|
||||||
|
end
|
||||||
|
it "bypasses if package is being removed" do
|
||||||
|
File.stubs(:readable?).with(centos_file).returns true
|
||||||
|
YAML.stubs(:load_file).with(centos_file).returns file_content
|
||||||
|
pkg = Puppet::Type.type(:package).new(:name => "pkg_with_version", :ensure => :absent)
|
||||||
|
pkg.provider.class.stubs(:name).returns :yum
|
||||||
|
expect(pkg[:ensure]).to eq :absent
|
||||||
|
end
|
||||||
|
it "bypasses if explicit version is given" do
|
||||||
|
File.stubs(:readable?).with(centos_file).returns true
|
||||||
|
YAML.stubs(:load_file).with(centos_file).returns file_content
|
||||||
|
pkg = Puppet::Type.type(:package).new(:name => "pkg_with_version", :ensure => '2')
|
||||||
|
pkg.provider.class.stubs(:name).returns :yum
|
||||||
|
expect(pkg[:ensure]).to eq '2'
|
||||||
|
end
|
||||||
|
it "bypasses if there is no file" do
|
||||||
|
File.stubs(:readable?).with(centos_file).returns false
|
||||||
|
pkg = Puppet::Type.type(:package).new(:name => "pkg_with_version", :ensure => :present)
|
||||||
|
pkg.provider.class.stubs(:name).returns :yum
|
||||||
|
expect(pkg[:ensure]).to eq :present
|
||||||
|
end
|
||||||
|
it "bypasses if file isn't correct" do
|
||||||
|
file_content = 'error'
|
||||||
|
File.stubs(:readable?).with(centos_file).returns true
|
||||||
|
YAML.stubs(:load_file).with(centos_file).returns file_content
|
||||||
|
pkg = Puppet::Type.type(:package).new(:name => "pkg_with_version", :ensure => :present)
|
||||||
|
pkg.provider.class.stubs(:name).returns :yum
|
||||||
|
expect(pkg[:ensure]).to eq :present
|
||||||
|
end
|
||||||
|
it "bypasses if there is no such package in the list" do
|
||||||
|
file_content = {}
|
||||||
|
File.stubs(:readable?).with(centos_file).returns true
|
||||||
|
YAML.stubs(:load_file).with(centos_file).returns file_content
|
||||||
|
pkg = Puppet::Type.type(:package).new(:name => "pkg_with_version", :ensure => :present)
|
||||||
|
pkg.provider.class.stubs(:name).returns :yum
|
||||||
|
expect(pkg[:ensure]).to eq :present
|
||||||
|
end
|
||||||
|
it "bypasses if provider is not apt or yum" do
|
||||||
|
File.stubs(:readable?).with(centos_file).returns true
|
||||||
|
YAML.stubs(:load_file).with(centos_file).returns file_content
|
||||||
|
pkg = Puppet::Type.type(:package).new(:name => "pkg_with_version", :ensure => :present, :provider => :gem)
|
||||||
|
pkg.provider.class.stubs(:name).returns :gem
|
||||||
|
expect(pkg[:ensure]).to eq :present
|
||||||
|
end
|
||||||
|
it "aliases true to :installed and looks for version" do
|
||||||
|
File.stubs(:readable?).with(centos_file).returns true
|
||||||
|
YAML.stubs(:load_file).with(centos_file).returns file_content
|
||||||
|
pkg = Puppet::Type.type(:package).new(:name => "pkg_with_version", :ensure => true )
|
||||||
|
pkg.provider.class.stubs(:name).returns :yum
|
||||||
|
expect(pkg[:ensure]).to eq '1'
|
||||||
|
end
|
||||||
|
it "aliases false to :absent" do
|
||||||
|
File.stubs(:readable?).with(centos_file).returns true
|
||||||
|
YAML.stubs(:load_file).with(centos_file).returns file_content
|
||||||
|
pkg = Puppet::Type.type(:package).new(:name => "pkg_with_version", :ensure => false )
|
||||||
|
pkg.provider.class.stubs(:name).returns :yum
|
||||||
|
expect(pkg[:ensure]).to eq :absent
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
@ -9,7 +9,7 @@ class puppet::thin (
|
|||||||
$rack_config = "/usr/share/puppet/ext/rack/files/config.ru"
|
$rack_config = "/usr/share/puppet/ext/rack/files/config.ru"
|
||||||
|
|
||||||
package { $puppet::params::thin_packages:
|
package { $puppet::params::thin_packages:
|
||||||
ensure => latest;
|
ensure => installed;
|
||||||
}
|
}
|
||||||
|
|
||||||
exec { "thin_install":
|
exec { "thin_install":
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
# environments. For more info, see the puppetdb docs.)
|
# environments. For more info, see the puppetdb docs.)
|
||||||
# ['puppetdb_version'] - The version of the `puppetdb` package that should
|
# ['puppetdb_version'] - The version of the `puppetdb` package that should
|
||||||
# be installed. You may specify an explicit version
|
# be installed. You may specify an explicit version
|
||||||
# number, 'present', or 'latest'. Defaults to
|
# number, 'present', or 'installed'. Defaults to
|
||||||
# 'present'.
|
# 'present'.
|
||||||
#
|
#
|
||||||
# Actions:
|
# Actions:
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
# ['puppet_conf'] - Puppet's config file; defaults to /etc/puppet/puppet.conf
|
# ['puppet_conf'] - Puppet's config file; defaults to /etc/puppet/puppet.conf
|
||||||
# ['puppetdb_version'] - The version of the `puppetdb` package that should
|
# ['puppetdb_version'] - The version of the `puppetdb` package that should
|
||||||
# be installed. You may specify an explicit version
|
# be installed. You may specify an explicit version
|
||||||
# number, 'present', or 'latest'. Defaults to
|
# number, 'present', or 'installed'. Defaults to
|
||||||
# 'present'.
|
# 'present'.
|
||||||
# ['restart_puppet'] - If true, the module will restart the puppet master when
|
# ['restart_puppet'] - If true, the module will restart the puppet master when
|
||||||
# necessary. The default is 'true'. If set to 'false',
|
# necessary. The default is 'true'. If set to 'false',
|
||||||
|
@ -43,7 +43,7 @@
|
|||||||
# (defaults to `puppetdb`; ignored for `embedded` db)
|
# (defaults to `puppetdb`; ignored for `embedded` db)
|
||||||
# ['puppetdb_version'] - The version of the `puppetdb` package that should
|
# ['puppetdb_version'] - The version of the `puppetdb` package that should
|
||||||
# be installed. You may specify an explicit version
|
# be installed. You may specify an explicit version
|
||||||
# number, 'present', or 'latest'. Defaults to
|
# number, 'present', or 'installed'. Defaults to
|
||||||
# 'present'.
|
# 'present'.
|
||||||
# ['manage_redhat_firewall'] - boolean indicating whether or not the module
|
# ['manage_redhat_firewall'] - boolean indicating whether or not the module
|
||||||
# should open a port in the firewall on redhat-based
|
# should open a port in the firewall on redhat-based
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
class { 'rabbitmq::server':
|
class { 'rabbitmq::server':
|
||||||
port => '5672',
|
port => '5672',
|
||||||
delete_guest_user => true,
|
delete_guest_user => true,
|
||||||
version => 'latest',
|
version => 'installed',
|
||||||
}
|
}
|
||||||
|
@ -22,10 +22,10 @@ $sat_base_channels, $sat_openstack_channel, $numtries = 10) {
|
|||||||
|
|
||||||
|
|
||||||
package { "yum-utils":
|
package { "yum-utils":
|
||||||
ensure => "latest"
|
ensure => "installed"
|
||||||
} ->
|
} ->
|
||||||
package { "subscription-manager":
|
package { "subscription-manager":
|
||||||
ensure => "latest"
|
ensure => "installed"
|
||||||
} ->
|
} ->
|
||||||
|
|
||||||
file { '/etc/pki/product':
|
file { '/etc/pki/product':
|
||||||
|
@ -3,7 +3,7 @@ class rsyslog::params {
|
|||||||
/(?i)(ubuntu|debian|redhat|centos)/: {
|
/(?i)(ubuntu|debian|redhat|centos)/: {
|
||||||
$rsyslog_package_name = 'rsyslog'
|
$rsyslog_package_name = 'rsyslog'
|
||||||
$relp_package_name = 'rsyslog-relp'
|
$relp_package_name = 'rsyslog-relp'
|
||||||
$package_status = 'latest'
|
$package_status = 'installed'
|
||||||
$rsyslog_d = '/etc/rsyslog.d/'
|
$rsyslog_d = '/etc/rsyslog.d/'
|
||||||
$rsyslog_conf = '/etc/rsyslog.conf'
|
$rsyslog_conf = '/etc/rsyslog.conf'
|
||||||
$rsyslog_queues_dir = '/var/lib/rsyslog'
|
$rsyslog_queues_dir = '/var/lib/rsyslog'
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
class ssh::client::install {
|
class ssh::client::install {
|
||||||
package { $ssh::params::client_package_name:
|
package { $ssh::params::client_package_name:
|
||||||
ensure => latest,
|
ensure => installed,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ class { 'memcached':
|
|||||||
class { 'swift':
|
class { 'swift':
|
||||||
# not sure how I want to deal with this shared secret
|
# not sure how I want to deal with this shared secret
|
||||||
swift_hash_suffix => $swift_shared_secret,
|
swift_hash_suffix => $swift_shared_secret,
|
||||||
package_ensure => latest,
|
package_ensure => installed,
|
||||||
}
|
}
|
||||||
|
|
||||||
# === Configure Storage
|
# === Configure Storage
|
||||||
|
@ -99,7 +99,7 @@ node swift_base {
|
|||||||
class { 'swift':
|
class { 'swift':
|
||||||
# not sure how I want to deal with this shared secret
|
# not sure how I want to deal with this shared secret
|
||||||
swift_hash_suffix => 'swift_shared_secret',
|
swift_hash_suffix => 'swift_shared_secret',
|
||||||
package_ensure => latest,
|
package_ensure => installed,
|
||||||
}
|
}
|
||||||
|
|
||||||
class { 'rsync::server':
|
class { 'rsync::server':
|
||||||
|
@ -92,7 +92,7 @@ node swift_base {
|
|||||||
class { 'swift':
|
class { 'swift':
|
||||||
# not sure how I want to deal with this shared secret
|
# not sure how I want to deal with this shared secret
|
||||||
swift_hash_suffix => 'swift_shared_secret',
|
swift_hash_suffix => 'swift_shared_secret',
|
||||||
package_ensure => latest,
|
package_ensure => installed,
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user