From e5b665af90962c39d416f92604168ee99b6b1efc Mon Sep 17 00:00:00 2001 From: Zach Crownover Date: Fri, 17 Nov 2017 11:37:25 +0000 Subject: [PATCH] Fix ensure with nonstandard versions This increases support for DragonFly BSD as well as FreeBSD, making them first class citizens for this module. Additionally, it creates a new structured fact called perl, which contains the various version numbers that can be referenced for what version of Perl is the system default. It was mainly added to properly support the config paths for the default @INC on DragonFly and FreeBSD. The cpan provider was updated to fix a few bugs around how it handled version strings, and using rubocop, some additional cleanup was done while there. --- lib/facter/perl_version.rb | 13 +++++ lib/puppet/provider/cpan/default.rb | 73 ++++++++++++----------------- manifests/config.pp | 45 +++++++----------- manifests/init.pp | 11 +++-- manifests/params.pp | 53 ++++++++++++--------- spec/classes/cpan_spec.rb | 2 +- 6 files changed, 99 insertions(+), 98 deletions(-) create mode 100644 lib/facter/perl_version.rb diff --git a/lib/facter/perl_version.rb b/lib/facter/perl_version.rb new file mode 100644 index 0000000..4433fb1 --- /dev/null +++ b/lib/facter/perl_version.rb @@ -0,0 +1,13 @@ +Facter.add(:perl) do + setcode do + perl = {} + current_info = Facter::Util::Resolution.exec('perl -v') + version = current_info.match(/v((\d+)\.(\d+)\.(\d*))/) + Facter.debug "Matching perl version as #{version}" + perl['version'] = version[1] + perl['majversion'] = version[2] + perl['minversion'] = version[3] + perl['subversion'] = version[4] + perl + end +end diff --git a/lib/puppet/provider/cpan/default.rb b/lib/puppet/provider/cpan/default.rb index 39ee9b8..d31736f 100644 --- a/lib/puppet/provider/cpan/default.rb +++ b/lib/puppet/provider/cpan/default.rb @@ -1,38 +1,31 @@ -Puppet::Type.type(:cpan).provide( :default ) do - @doc = "Manages cpan modules" +Puppet::Type.type(:cpan).provide(:default) do + @doc = 'Manages cpan modules' - commands :cpan => 'cpan' - commands :perl => 'perl' - confine :osfamily => [:Debian, :RedHat, :Windows] + commands cpan: 'cpan' + commands perl: 'perl' + confine osfamily: %i[Debian DragonFly FreeBSD RedHat Windows] ENV['PERL_MM_USE_DEFAULT'] = '1' - def install - end + def install; end - def force - end + def force; end def latest? - if resource[:local_lib] - ll = "-Mlocal::lib=#{resource[:local_lib]}" + ll = "-Mlocal::lib=#{resource[:local_lib]}" if resource[:local_lib] + current = `perl #{ll} -M#{resource[:name]} -e 'print $#{resource[:name]}::VERSION' 2>/dev/null;` + return false if current == '' + cpan_str = `perl #{ll} -e 'use CPAN; my $mod=CPAN::Shell->expand("Module","#{resource[:name]}"); printf("%s", $mod->cpan_version eq "undef" || !defined($mod->cpan_version) ? "-" : $mod->cpan_version);'` + latest = cpan_str.match(/^[a-zA-Z]?([0-9]+.?[0-9]*\.?[0-9]*)$/)[1] + if Puppet::Util::Package.versioncmp(latest.chomp, current.chomp) > 0 + return true end - current_version=`perl #{ll} -M#{resource[:name]} -e 'print $#{resource[:name]}::VERSION'` - cpan_str=`perl #{ll} -e 'use CPAN; my $mod=CPAN::Shell->expand("Module","#{resource[:name]}"); printf("%s", $mod->cpan_version eq "undef" || !defined($mod->cpan_version) ? "-" : $mod->cpan_version);'` - latest_version=cpan_str.match(/^[0-9]+.?[0-9]*$/)[0] - current_version.chomp - latest_version.chomp - if current_version < latest_version - return false else return true end + false end def create Puppet.info("Installing cpan module #{resource[:name]}") - if resource[:local_lib] - ll = "-Mlocal::lib=#{resource[:local_lib]}" - end - + ll = "-Mlocal::lib=#{resource[:local_lib]}" if resource[:local_lib] umask = "umask #{resource[:umask]};" if resource[:umask] - Puppet.debug("cpan #{resource[:name]}") if resource.force? Puppet.info("Forcing install for #{resource[:name]}") @@ -41,24 +34,20 @@ def create system("#{umask} yes | perl #{ll} -MCPAN -e 'CPAN::install #{resource[:name]}'") end - #cpan doesn't always provide the right exit code, so we double check + # cpan doesn't always provide the right exit code, so we double check system("perl #{ll} -M#{resource[:name]} -e1 > /dev/null 2>&1") - estatus = $?.exitstatus + estatus = $CHILD_STATUS.exitstatus - if estatus != 0 - raise Puppet::Error, "cpan #{resource[:name]} failed with error code #{estatus}" - end + raise Puppet::Error, "cpan #{resource[:name]} failed with error code #{estatus}" if estatus != 0 end - def destroy - end - + def destroy; end + def update Puppet.info("Upgrading cpan module #{resource[:name]}") Puppet.debug("cpan #{resource[:name]}") - if resource[:local_lib] - ll = "-Mlocal::lib=#{resource[:local_lib]}" - end + + ll = "-Mlocal::lib=#{resource[:local_lib]}" if resource[:local_lib] umask = "umask #{resource[:umask]};" if resource[:umask] if resource.force? @@ -67,20 +56,17 @@ def update else system("#{umask} yes | perl #{ll} -MCPAN -e 'CPAN::install #{resource[:name]}'") end - estatus = $?.exitstatus - - if estatus != 0 - raise Puppet::Error, "CPAN::install #{resource[:name]} failed with error code #{estatus}" - end + estatus = $CHILD_STATUS.exitstatus + + raise Puppet::Error, "CPAN::install #{resource[:name]} failed with error code #{estatus}" if estatus != 0 end def exists? - if resource[:local_lib] - ll = "-Mlocal::lib=#{resource[:local_lib]}" - end + ll = "-Mlocal::lib=#{resource[:local_lib]}" if resource[:local_lib] + Puppet.debug("perl #{ll} -M#{resource[:name]} -e1 > /dev/null 2>&1") output = `perl #{ll} -M#{resource[:name]} -e1 > /dev/null 2>&1` - estatus = $?.exitstatus + estatus = $CHILD_STATUS.exitstatus case estatus when 0 @@ -92,5 +78,4 @@ def exists? raise Puppet::Error, "perl #{ll} -M#{resource[:name]} -e1 failed with error code #{estatus}: #{output}" end end - end diff --git a/manifests/config.pp b/manifests/config.pp index fb327c6..5224b90 100644 --- a/manifests/config.pp +++ b/manifests/config.pp @@ -11,38 +11,27 @@ owner => root, group => root, mode => '0755', - } - file { '/etc/perl/CPAN/Config.pm': - ensure => present, - owner => root, - group => root, - mode => '0644', - content => template($::cpan::config_template), - require => File['/etc/perl/CPAN'], + before => File[$perl_config], } } - 'RedHat': { - if versioncmp($::operatingsystemmajrelease, '6') >= 0 and $::operatingsystem != 'Fedora' { - file { '/usr/share/perl5/CPAN/Config.pm': - ensure => present, - owner => 'root', - group => 'root', - mode => '0644', - content => template($::cpan::config_template), - } - } else { - file { '/usr/lib/perl5/5.8.8/CPAN/Config.pm': - ensure => present, - owner => 'root', - group => 'root', - mode => '0644', - content => template($::cpan::config_template), - } + 'DragonFly', 'FreeBSD': { + file { [ '/usr/local/perl5', "/usr/local/perl5/5.${::perl['minversion']}", "/usr/local/perl5/5.${::perl['minversion']}/CPAN" ]: + ensure => directory, + owner => 0, + group => 0, + mode => '0755', + before => File[$perl_config], } } - default: { - fail("Module ${module_name} is not supported on ${::osfamily} os.") - } + default: { } + } + + file { $::cpan::perl_config: + ensure => present, + owner => $root_user, + group => $root_group, + mode => '0644', + content => template($::cpan::config_template), } } } diff --git a/manifests/init.pp b/manifests/init.pp index eb2472b..29e5bc3 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -42,7 +42,10 @@ $local_lib = $cpan::params::local_lib, $config_template = $cpan::params::config_template, $config_hash = $cpan::params::config_hash, + $root_user = $cpan::params::root_user, + $root_group = $cpan::params::root_group, $package_ensure = $cpan::params::package_ensure, + $perl_config = $cpan::params::perl_config, $ftp_proxy = $cpan::params::ftp_proxy, $http_proxy = $cpan::params::http_proxy, $urllist = $cpan::params::urllist, @@ -62,9 +65,9 @@ } validate_array($urllist) - anchor { 'cpan::begin': } -> - class { '::cpan::install': } -> - class { '::cpan::config': } -> - anchor { 'cpan::end': } + anchor { 'cpan::begin': } + -> class { '::cpan::install': } + -> class { '::cpan::config': } + -> anchor { 'cpan::end': } } diff --git a/manifests/params.pp b/manifests/params.pp index ee80a1f..4968b8b 100644 --- a/manifests/params.pp +++ b/manifests/params.pp @@ -4,16 +4,16 @@ # class cpan::params { - $manage_config = true - $installdirs = 'site' - $local_lib = false - $config_template = 'cpan/cpan.conf.erb' - $config_hash = { 'build_requires_install_policy' => 'no' } - $package_ensure = 'present' - $common_package = ['gcc','make'] - $ftp_proxy = undef - $http_proxy = undef - $urllist = [] + $manage_config = true + $installdirs = 'site' + $local_lib = false + $config_template = 'cpan/cpan.conf.erb' + $config_hash = { 'build_requires_install_policy' => 'no' } + $package_ensure = 'present' + $common_package = ['gcc','make'] + $ftp_proxy = undef + $http_proxy = undef + $urllist = [] unless $installdirs =~ /^(perl|site|vendor)$/ { fail('installdirs must be one of {perl,site,vendor}') @@ -27,28 +27,39 @@ case $::osfamily { 'Debian': { $common_os_package = ['perl-modules'] + $perl_config = '/etc/perl/CPAN/Config.pm' + $root_user = 'root' + $root_group = 'root' if $local_lib { - $local_lib_package = ['liblocal-lib-perl'] + $local_lib_package = ['liblocal-lib-perl'] } else { - $local_lib_package = [] + $local_lib_package = [] } } 'RedHat': { $common_os_package = ['perl-CPAN'] - - if $local_lib { - if ($::operatingsystem == 'RedHat' and versioncmp($::operatingsystemmajrelease, '6') >= 0) { - $local_lib_package = ['perl-local-lib'] - } elsif ($::operatingsystem == 'Fedora' and versioncmp($::operatingsystemmajrelease, '16') >=0) { - $local_lib_package = ['perl-local-lib'] + case $::operatingsystemmajrelease { + 5, 6: { + $local_lib_package = ['perl-local-lib'] + $perl_config = '/usr/share/perl5/CPAN/Config.pm' + $root_user = 'root' + $root_group = 'root' } - } else { - $local_lib_package = [] + 7: { + $root_user = 'root' + $root_group = 'wheel' + } + default: { } } } + 'DragonFly', 'FreeBSD': { + $perl_config = "/usr/local/perl5/5.${::perl['minversion']}/CPAN/Config.pm" + $root_user = 'root' + $root_group = 'wheel' + } default: { fail("Module ${module_name} is not supported on ${::osfamily}") } } - $package_name = concat($common_package,$common_os_package,$local_lib_package ) + $package_name = concat($common_package,$common_os_package,$local_lib_package ) } diff --git a/spec/classes/cpan_spec.rb b/spec/classes/cpan_spec.rb index b5e67aa..21925de 100644 --- a/spec/classes/cpan_spec.rb +++ b/spec/classes/cpan_spec.rb @@ -74,7 +74,7 @@ describe 'cpan::config on RedHat and operatingsystemrelease 7' do let(:facts) { super().merge(:osfamily => 'RedHat', :operatingsystemmajrelease => '7') } it { should contain_file('/usr/share/perl5/CPAN/Config.pm').with_owner('root') } - it { should contain_file('/usr/share/perl5/CPAN/Config.pm').with_group('root') } + it { should contain_file('/usr/share/perl5/CPAN/Config.pm').with_group('wheel') } it { should contain_file('/usr/share/perl5/CPAN/Config.pm').with_mode('0644') } end