refactor use of ensure_packages to install new versions of php packages

23 views
Skip to first unread message

jochen....@gmail.com

unread,
Oct 12, 2020, 5:10:34 AM10/12/20
to Puppet Users
Hi all,

I posted a question on Stackoverflow before the weekend, but no responses and not many views yet, unfortunately. So please forgive me asking this again here. refactor ensure_packages to switch version of installed packages https://stackoverflow.com/q/64284862/13088564?sem=2


I am successfully installing several PHP modules by version with puppet on Debian linux like this:

$php_version = '7.3' 
ensure_packages([ 
    "php$php_version-xml", 
     "php$php_version-zip", 
     "php$php_version-curl", 
     "php$php_version-mbstring", 
     "libapache2-mod-php$php_version",
 ], 
 { 'ensure' => 'present', } )

now I want to prepare for an update from PHP 7.3 to 7.4. This basically works, but the 7.3 packages stay installed. I would like to adapt the code to remove the old packages. I am looking for a way to reuse the list of packages of modules for uninstalling.

I am thinking of a signature like this

class profile::software::apache (
     $php_version = '7.4',
     $php_remove = ['7.0‘, ‘7.3']
    , #... 
) {

$myPackages = [
     "php$php_version-xml",
     "php$php_version-zip",
     "php$php_version-curl",
     "php$php_version-mbstring",
     "libapache2-mod-php$php_version",
 ] 
 
ensure_packages($myPackages, {
     'ensure' => 'present', 
 } ) 

 $php_remove.each | String $php_version | { 
     ensure_packages($myPackages,
     { 
          'ensure' => 'absent', 
     }  )
 }
 }

Is there a way to solve this?

thx

A Manzer

unread,
Oct 12, 2020, 7:46:04 AM10/12/20
to Puppet Users
Seems pretty smart to me, tbh.

The only problem is that $myPackages is constant, so already includes the "7.4" values from $php_version.  You'll need to declare a new list (because you can't change variables) inside your .each block.

$php_remove.each | String $php_str_remove | {
     $myRemovePackages = [
         "php${php_str_remove}-xml",
         "php${php_str_remove}-zip",
         "php${php_str_remove}-curl",
         "php${php_str_remove}-mbstring",
         "libapache2-mod-php${php_str_remove}",
    ]
     ensure_packages($myRemovePackages,

Jochen Haeberle

unread,
Oct 12, 2020, 7:51:12 AM10/12/20
to puppet...@googlegroups.com
thx for the smart ;-)

but when I redeclare the list, I end up keeping two lists of packages. The guy who I am, I will definitely fuck this up regularly… and that’s back to the root of my problem… I would like to somehow reuse the $myPackages structure with different values for $php_version. 

Mhmm… as I write this this sounds like a use for a template…

Regards
Jochen

--
You received this message because you are subscribed to the Google Groups "Puppet Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to puppet-users...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/puppet-users/470cea3c-b64f-4666-827f-0bccfb101afcn%40googlegroups.com.

A Manzer

unread,
Oct 12, 2020, 7:56:27 AM10/12/20
to Puppet Users
If you redeclare the list outside the .each block, you'll end up with the same list.  Also if you redeclare it outside, against the $php_remove array, you'll get something weird.

If you redeclare it inside the .each block, it'll be local to that block, get destroyed on the second run, and you'll end up with a fresh copy for the next value of your $php_remove array.

You need to make sure you don't reuse variable names so you don't get confused, but it'll work.


If you want to use the same package list in both places, you may be able to play some games with single- and double-quoting, but I don't think I'd recommend that.

Jochen Haeberle

unread,
Oct 12, 2020, 8:03:18 AM10/12/20
to puppet...@googlegroups.com
I think you will get sort of „cannot redeclare“… otherwise I agree, it would work like you suggest.

But with the solution you propose, I guess I will have one structure for the packages to be installed and another for the ones to be removed.

But I want to manage only one list of packages… more save against errors managing the list… I have those packages all over the place...

I will have to think along the lines of single and double quoting… thx

A Manzer

unread,
Oct 12, 2020, 8:17:15 AM10/12/20
to Puppet Users
I don't know if it'll work, but you might be able to do something like this:

$php_package_1 = 'php${php_version}-xml'  #single quoted to prevent interpolation

$install_versions.each | String $php_version | {
    $php_install_1 = "${php_package_1}"  #double quoted to now interpolate
    ensure_packages($php_install_1, {ensure => present})
}

But this is a mess of reusing variables names.

Oh, you could also store the list of packages to be installed in Hiera, so that you have one list, but you can reference it in two different places (outside, and inside the loop).

Garrett Honeycutt

unread,
Oct 12, 2020, 1:07:26 PM10/12/20
to puppet...@googlegroups.com
> --
> You received this message because you are subscribed to the Google
> Groups "Puppet Users" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to puppet-users...@googlegroups.com
> <mailto:puppet-users...@googlegroups.com>.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/puppet-users/64abfa9c-5b7a-4aac-8a78-8e5152e8d66cn%40googlegroups.com
> <https://groups.google.com/d/msgid/puppet-users/64abfa9c-5b7a-4aac-8a78-8e5152e8d66cn%40googlegroups.com?utm_medium=email&utm_source=footer>.

Hi Jochen,

Can Puppet handle this, yes! Should it, absolutely not. As you have seen
from the posts you are going to quickly have a huge list of things you
do not want on your system which becomes hard to manage. Instead of
that, suggest you manage what packages are available in your
repositories. You can tell puppet to install php-whatever and not
specify 7.3 vs 7.4 vs 7.4.2, etc. You could have systems in different
environments use different paths in your repo definitions such that you
can test new packages in a pre-production environment and then update
the URL's in other environments. You will end up with a much more
reliable change management process for patching than attempting to track
all the versions in Puppet.

Best regards,
-g


--
Garrett Honeycutt

Jochen Haeberle

unread,
Oct 13, 2020, 12:22:13 PM10/13/20
to puppet...@googlegroups.com
Hi Garrett,

thx for the thoughts. I am basically doing as you suggest. Whenever possible I hold to latest versions of package maintainers

But Debian often comes with old versions of PHP which poses a problem. So I tend to use sury repositories to install newer but well tested packages of PHP. This repository offers several versions of PHP, at the moment mostly 7.3 and 7.4. Common software packages now tend to switch to PHP 7.4 so sometime you sort of should follow that move to keep up to date.
Debian 9 came with PHP 7.0 I think (7.1 the most), which should not be used any more, but Debian 9 is still actively updated.

So whether I am on dev, preproduction, staging or live. If I do go this way for PHP, I will have to decide which version of PHP to use. And when I decide to switch the version, I can easily have Puppet do that, but the old versions keep installed and will be updated as well, which is undesirable.

Regards
Jochen

To unsubscribe from this group and stop receiving emails from it, send an email to puppet-users...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/puppet-users/eb2655bd-b4ee-d487-e646-1ad2ad537120%40garretthoneycutt.com.

Jochen Haeberle

unread,
Oct 13, 2020, 12:26:35 PM10/13/20
to puppet...@googlegroups.com
Hi all,

I solved this with the use of puppet iteration functions:

class profile::software::apache (
  $php_version    = '7.4',
  $php_remove     = ['7.0‘, ‘7.3'],
  #...
) {
  # build a hash of PHP Versions with a value of either present or absent
  # and iterate over it with each
  $phpInstallHash = { $php_version => 'present' }
  #notify { "Value of phpRemove: ${php_remove}": }
  if $php_remove {
    # We have the array, use the map function to build remove hash
    $phpRemoveHash = $php_remove.map |$version| {
      { $version => 'absent' }
    }
    $phpFullHash = $phpInstallHash + $phpRemoveHash
  } else {
    $phpFullHash = $phpInstallHash
  }
  #notify { "phpHash to iterate over to install/uninstall: ${phpFullHash}": }

  #iterate over the result installing/uninstalling
  $phpFullHash.each | $php_version, $ensure_value | {
    ensure_packages([
      "php$php_version-xml",
      "php$php_version-zip",
      "php$php_version-curl",
      "php$php_version-mbstring",
      "libapache2-mod-php$php_version",
    ],
      {
        'ensure' => $ensure_value,
        require  => [Class['apt::update'],
          Apt::Source['source_php_sury'],
        ],
        notify   => Class['apache::service'],
      }
    )

  }
}

It works for me. I answered my StackOverflow question as well. Any thoughts?

As Garret pointed out, this for sure is not a recommended or usual way to do things. The need for this stems from my use of the Sury PHP repository, which offers several versions of PHP. I chose to use with 7.3 or 7.4 and get all important and security related from that tree, so it’s not like pinning a package to a fixed version.

regards,
Jochen
 

A Manzer

unread,
Oct 13, 2020, 12:32:46 PM10/13/20
to Puppet Users
Glad you managed to figure it out, and thanks for posting your solution for posterity!
Reply all
Reply to author
Forward
0 new messages