Use command output in puppet ensure_packages package definition - puppet

I am currently installing kernel headers from a puppet manifest with the following:
ensure_packages([
'linux-headers-4.19.0-12-cloud-amd64',
],
{ 'ensure' => 'present' })
It would make more sense if I could use the uname -r command rather than hardcoding the kernel version, so that the kernel version instance where it is being installed is retrieved automatically.
So I've tried configuring this with the following.
ensure_packages([
"linux-headers-$(uname -r)",
],
{ 'ensure' => 'present' })
But this is failing as it doesn't seem to resolve the command.
Is this even possible in puppet?

Is this even possible in puppet?
Yes, it is possible to run an external command during catalog building, capture the output, and use that like any other string to inform the details of the catalog. You would accomplish that with the help of the generate() function. You might need to specify an explicit path to the command.
But that's not what you actually want.
If you perform the evaluation during catalog building then you will get data pertaining to the machine on which the catalog is built, which is usually a different machine from the one to which the catalog will be applied. The most appropriate vehicle for conveying target machine details to the catalog builder is facts. You would want to check whether the core (built-in) kernel fact already provides what you want. If not, then it should be pretty easy to write a custom fact for this purpose.

Related

Maintain mysql configuration with puppet

I recently add the mysql module from puppetLabs in version 7.0 on our RHEL Satellite for managing all our MySql's servers and hold them with idempotency configuration and bloc any unwanted configuration.
In this case, a user with Granted privileges is able to create a Database (like root#localhost) and so add manually a Database with the command create database dbname; for example.
Problem, If i run my pupppet agent -t on my lab server, puppet is just ensuring that databeses defined in my smart class "Databeses" exist (or not) and do nothing...
The result expected was it can remove any modification (like database creation) when ran the agent.
Is there a way to do this ?
Thanks for replies
Since Mysql_database is an "ensurable" plugin type that implements prefetching, you should be able to use the Resources resource type to purge any unmanaged databases that are created on managed nodes. It might look something like this:
resources { 'mysql_database': purge => true }
Do this only if you're certain that you really want it!
Additionally, you might want to try some runs in --noop mode to look for issues before going live. That could help you recognize unanticipated issues, such as databases you want to keep -- belonging to MySQL itself, for example -- but are not currently managing.

How to call a puppet provider method from puppet manifest?

I'm using the ibm_installation_manager module from the puppet forge and it is a bit basic because IBM wrote Installation Manager in a time where idempotency was done much.
ref: https://forge.puppet.com/puppetlabs/ibm_installation_manager
As such it does not cater nicely for upgrades - so the module will not detect if an upgrade is needed, stop existing processes, do the upgrade and then start the processes again. It will just detect if an upgrade is needed and try to install the desired version and if that constitutes an upgrade that's great, but it will probably fail due to running instances.
So I need to implement some "stop processes" pre-upgrade functionality.
I need to mention at this point I'm new to ruby and fairly new to puppet.
The provider that the module uses (imcl.rb) has an exists method.
The ideal way for me to detect if an upgrade is going to happen (and stop the instances if it is) would be for my puppet manifest to be able to somehow call the exists method. Is this possible?
Or how would you approach this problem?
Something like imcl.exists(ibm_pkg["my_imcl_pkg_resource"])
The ideal way for me to detect if an upgrade is going to happen (and stop the instances if it is) would be for my puppet manifest to be able to somehow call the exists method. Is this possible?
No, it is not possible, at least not in any useful way. Your manifests describe how to build a catalog of resources describing the target state of the machine. In a master / agent setup, this happens on the master. The catalog is then used as input to a separate step, in which it is transferred to the target machine and applied there. It is in this second step that providers are engaged.
To the extent that you want the contents of your catalogs to be influenced by the current state of the target machine, the Puppet mechanism for that is to convey the needed state details to the catalog builder in the form of facts. It is relatively straightforward to add your own facts. Indeed, there are at least two distinct, non-exclusive mechanisms, going under the names "external facts" and "custom facts".

Using puppet to build from source

How can I use puppet to build from source without using multiple Exec commands?. Do we have modules for it on forge that I could use?
It's possible to use Puppet to build applications from source without using execs, possibly with a custom written type and provider. Otherwise, yes, it'd have to be a few different exec resources with onlyif, creates etc. statements to stop them running every time the agent ran.
Puppet's model of configuration management is known as a desired state model: you define the end state of the system and let the system. This is why exec's are generally avoided in Puppet: they don't fit a desired state model. It also makes things like updating the application, or dealing with unknowns like a partial failure of the compilation that creates a required file.
In my opinion, I would not recommend using configuration management to build applications from source at all. There are a few issue inherent with doing so (this is not just for Puppet, but most config management languages):
Slower runs, as running the compilation can be longer and detecting that it's complete is normally a slightly trickier tasks
Issues with half complete state or failure: if the compilation breaks halfway through it's both harder to detect and resolve
Making the compilation idempotent: You have to wrap the command in logic that detects if the installation has already been done. However, this is difficult, as things like the detection of a flag file or particular binary could occur even when the compilation ends in failure
Upgrading or changing: There's no easy way to upgrade or change the application. A package would be easier to do this with.
This sounds like something that would be better served by packaging, using tools such as FPM or just native package building tools such as rpmbuild.

puppet fileserver distribute binaries

Well, question is not new but I still unable to find any nice solution.
I distributing binaries 100-300mb files via puppet fileserver, but it works really bad in case of performance I'm sure because of md5 checks. Now I have more than 100 servers and my puppet master works really hard to manage all that md5 computation checks. In puppet 3.x checksum for file{} does not work. I'm unable to update to puppet 4.x and I have no chance to change flow. files should came from puppet fileserver.
So I can't believe that there is no custom file type with fixed checksum option, but I can't find it :(
Or maybe there is any other way to download files from puppet fileserver ?
Please any advice will help!
rsync or pack as a native package impossible option to me.
It is indeed reasonable to suppose that using the default checksum algorithm (MD5) when managing large files will have a substantial performance impact. The File resource has a checksum attribute that is supposed to be usable to specify an alternative checksumming algorithm among those supported by Puppet (some of which are not actually checksums per se), but it was buggy in many versions of Puppet 3. At this time, it does not appear that the fix implemented in Puppet 4 has been backported to the Puppet 3 series.
If you need only to distribute files, and don't care about afterward updating them or maintaining their consistency via Puppet, then you could consider turning off checksumming altogether. That might look something like this:
file { '/path/to/bigfile.bin':
ensure => 'file',
source => 'puppet:///modules/mymodule/bigfile.bin',
owner => 'root',
group => 'root',
mode => '0644',
checksum => 'none',
replace => false
}
If you do want to manage existing files, however, then Puppet needs a way to determine whether a file already present on the node is up to date. That's the one of the two main purposes of checksumming. If you insist on distributing the file via the Puppet file server, and you are stuck on Puppet 3, then I'm afraid you are out of luck as far as lightening the load. Puppet's file server is tightly integrated with the File resource type, and not intended to serve general purposes. To the best of my knowledge, there is no third-party resource type that leverages it. In any case, the file server itself is a major contributor to the problem of File's checksum parameter not working -- buggy versions do not perform any type of checksumming other than MD5.
As an alternative, you might consider packaging your large file in your system's native packaging format, dropping it in your internal package repository, and managing the package (via a Package resource) instead of managing the file directly. That does get away from distributing it via the file server, but that's pretty much the point.

Reinstalling package if specific file is missing

I need to reinstall a package with Puppet if a specific file is missing. How can I achive this? In never versions of Puppet is a the onlyif parameter available but we still use Puppet 3.1.
Do not mistake Puppet for some kind of baroque script engine. Reinstalling a package is an action, whereas Puppet classes, resources, and DSL in general focus on describing state. Puppet's general paradigm is that you tell it what state you want, and it figures out for itself what actions, if any, to take to achieve that state. Even Exec resources are best conceptualized and used as representations of state to be managed.
Puppet Package resources do not recognize a state of "installed but broken", or any similar thing, and therefore they have no sense of a need to reinstall (as opposed to updating) a package, nor any mechanism for doing so.
If your concern is with only one specific file that you expect the package to provide, then you should consider putting that file under direct management (via a File resource) instead of relying on a package reinstallation to recover it if it should go missing.
However, you should consider what flaw in your system's configuration or security policy affords any plausible likelihood that random system files will unexpectedly go missing. You should especially do this if you are using the file in question as a canary to detect broader damage.
Nevertheless, if you remain firm about doing what you ask, then an Exec resource can help. The details of what you would need are unclear, but you can take this as a pattern:
exec { 'Ensure package mypackage good':
command => '/usr/bin/yum -y reinstall mypackage',
creates => '/path/to/some_file',
require => Package['mypackage']
}
The Exec type also has unless and onlyif parameters (including in Puppet 3.1), but the creates parameter serves the specific case of using the presence or absence of a file to determine whether the command needs to be run, which is exactly what you want.
Note also the require parameter. This presumes that package 'mypackage' is under Puppet management (not shown), and guarantees that the Exec will not be synced before the package. That way, if the package is altogether absent, you can be sure that Puppet will install it (supposing that's what you have specified) before testing the presence of any file it is expected to provide.

Resources