download jdk 8 using puppet on windows 10 - puppet

I need to download jdk-8u45-windows-x64.exe on windows and install java. when i use pget it downloads a corrupt/unreadable file.
download.pp
class role::java {
pget{'Download java':
source => 'http://download.oracle.com/otn-pub/java/jdk/8u45-b15/jdk-8u45-windows-x64.exe',
target => 'C:\Users\Administrator\Downloads',
}
exec{"jdkinstaller":
  command => "C:\Users\Administrator\Downloads\jdk-8u45-windows-x64.exe /s ADDLOCAL=\"ToolsFeature,DemosFeature,SourceFeature\" ",
  creates => 'C:\Program Files\Java\jdk1.8.0_45\bin\javac.exe',
  logoutput => 'true',
 }
}
I tried using cyberious/windows_java from puppet forge but it didnt work either.
is there any other way to install java on windows.

Two issues in this manifest
The one Exception_al is mentioned.
as mentioned below in picture, you should escape "\". For this you have to use "/" instead of "\"

Related

Verifying if package is installed before downloading it in PUPPET

That is my manifest code which download, install and remove installer on a host.
class googlechrome_2 {
package { 'GoogleChrome':
ensure => installed,
source => 'C:\Soft\ChromeSetup.msi',
install_options => ['/qn'],
require => File['GoogleChromeMsi'],
}
file { 'GoogleChromeMsi':
ensure => file,
path => 'C:\Soft\ChromeSetup.msi',
source => 'puppet:///files/production/ChromeSetup.msi',
}
exec { 'msi_removing':
command => 'C:\Windows\System32\cmd.exe /c del C:\Soft\ChromeSetup.msi',
}
}
In this case my windows host always download chromesetup.msi regardless if google chrome already installed or not. How can I realize kind of "if condition" here to avoid downloading msi package each time in case if this package already installed?
In this case my windows host always download chromesetup.msi regardless if google chrome already installed or not.
Yes. Having the File resource in the node's catalog specifies that the file should be managed. Therefore, if it is not initially in the target state then Puppet will attempt to fix that.
By managing the file present but also including an Exec that removes the file, you ensure that the target node cannot achieve a stable state.
How can I realize kind of "if condition" here to avoid downloading msi package each time in case if this package already installed?
Simplest option: don't remove the installer.
Variation: Put the installer in an accessible network folder, so that you not only don't remove it, but you also don't install it.
If you really want a conditional: then it should be based on a custom fact that reports on the installation status of the package in question. You then use a Puppet if statement to control the contents of the node's catalog appropriately. Something along these lines, for example:
package { 'GoogleChrome':
ensure => 'installed',
source => 'C:\Soft\ChromeSetup.msi',
install_options => ['/qn'],
# relationhip with File['GoogleChromeMsi'] now declared on the other end
}
if $facts['chrome_is_installed'] {
file { 'GoogleChromeMsi':
ensure => 'absent',
path => 'C:\Soft\ChromeSetup.msi',
}
} else {
file { 'GoogleChromeMsi':
ensure => 'file',
path => 'C:\Soft\ChromeSetup.msi',
source => 'puppet:///files/production/ChromeSetup.msi',
before => Package['GoogleChrome'],
}
exec { 'msi_removing':
command => 'C:\Windows\System32\cmd.exe /c del C:\Soft\ChromeSetup.msi',
require => Package['GoogleChrome'],
}
}
I've solved this by using network shared folder in the package source:
class googlechrome_smb {
package { 'Google Chrome':
ensure => installed,
source => '\\\xxx.xxx.xxx.xxx\winfiles\ChromeSetup.msi',
install_options => ['/qn'],
}
}

Puppet code to download extract and install

I have a file at some web URL (http://www.somewhere.com/something.tar.gz).
This is direct download link.
I need a puppet code that would download this file, extract it and install the file.
Can we do this using package {} in puppet?
There isn't really an intrinsic provider for the package type that understands tarballs. There is, however, this VoxPopuli module: https://forge.puppet.com/puppet/archive which was recently Puppet certified and should do what you need.
Note under their usage example it could be modified for your needs like:
archive { '/tmp/something':
ensure => present,
extract => true,
extract_path => '/tmp',
source => 'http://www.somewhere.com/something.tar.gz',
checksum => 'checksum hash',
checksum_type => 'sha1',
creates => '/tmp/something',
cleanup => true,
}

Custom fact should run after a package is installed

I have a small custom fact in a my php module
Facter.add('php_extension_version') do
setcode do
Facter::Core::Execution.exec("php -i | awk '/^PHP Extension =>/ { print $4}'") || nil
end
end
This obviously requires the php binary to be installed. However, I noticed that all facts are run once before applying the catalog, so this fact is invalid before php installed.
Is there any way of gathering the information after the module is installed? Is there perhaps another way of exposing this information except facter?
Update
I'm using the two facts to determine which of multiple .so files is the right one to install:
if $php_zts_enabled {
$so_name = "newrelic-$php_extension_version.so"
} else {
$so_name = "newrelic-$php_extension_version-zts.so"
}
file {"/usr/lib64/php5/extensions/newrelic.so":
source => "file:///opt/newrelic-php5-$version-linux/agent/x64/$so_name",
owner => root,
group => root,
mode => 0644,
notify => Service['apache'],
require => Exec["extract-php-agent-$version"]
}
The files that are located in the agent/x64 directory can be
newrelic-20060613.so newrelic-20090626-zts.so newrelic-20121212.so newrelic-20131226-zts.so
newrelic-20060613-zts.so newrelic-20100525.so newrelic-20121212-zts.so
newrelic-20090626.so newrelic-20100525-zts.so newrelic-20131226.so
You essentially have only two opportunities to execute code on the node:
As part of a Facter fact. As you are aware, this happens before puppet applies a catalog, so any facts dependent on the results of the puppet run will not be useful until the next run.
As part of a custom provider. You can create a custom type and provider for installing the extensions that checks the node state before deciding what to do. Providers execute on the node, and as long as you know the overall provider lifecycle you can make this happen after the PHP install. However, this is incredibly complex compared to normal puppet modules.
Outside of those options, the normal way of doing this would be to enforce the version and configuration of php within your own manifests, and then pass that information to here. You should already know the version of PHP and its extensions based on what packages you have installed.
I would modify the fact so that it's present only when the binary is present (hence it won't be present at the very first run).
Facter.add('php_extension_version') do
setcode do
if system("which php > /dev/null 2>&1")
Facter::Core::Execution.exec("php -i | awk '/^PHP Extension =>/ { print $4}'") || nil
end
end
end
and then in your manifest you'd wrap the original code in the if
if $php_extension_version {
if $php_zts_enabled {
$so_name = "newrelic-$php_extension_version.so"
} else {
$so_name = "newrelic-$php_extension_version-zts.so"
}
file {"/usr/lib64/php5/extensions/newrelic.so":
source => "file:///opt/newrelic-php5-$version-linux/agent/x64/$so_name",
owner => root,
group => root,
mode => 0644,
notify => Service['apache'],
require => Exec["extract-php-agent-$version"]
}
}

Predicting package version

I'm configuring syslog-ng through puppet on my servers. The configuration files are very different between versions 2.x, 3.1 and 3.3 . On my hosts, depending on the operating system (centos5, centos6, debian 7, ubuntu), the available syslog-ng version will vary.
I had 2 ideas to adapt the configuration of syslog-ng to the correct version :
Custom Fact : It's easy to write a custom fact to test the installed version of syslog-ng. But this fact will be useless if syslog-ng is not already installed.
Conditions in the manifest : I find it a bit ugly to define a "case" in the manifest wich would determine the version of syslog-ng that the operatingsystem provides.
For me, the cleanest way to do this is to test which version of the package is available through the operatingsystem before installation.
A facter could do this, but I guess it would be a bit difficult.
Is there a puppetish way to solve my problem ?
There is indeed puppet-ish way to solve this problem!
You can combine $::osfamily with $::operatingsystemrelease to do something like this in your manifests:
case $::osfamily {
'CentOS': {
case $::operatingsystemrelease {
/^6/: { include syslog-ng::centos6 }
/^5/: { include syslog-ng::centos5 }
default: { notice("This operating system release for CentOs '${::operatingsystemrelease}' is not supported.")
}
}
default: { notice "Unsupported osfamily ${::osfamily}" }
}
I am not sure I understood all of your problem. In any case, one can use puppet package type to ensure a particular version and use $lsbdistdescription to get the OS name. For example :
package { 'syslog-ng' :
ensure => $::lsbdistdescription {
'/CentOS 7/': => "3.2",
'/CentOS 6/': => "3.1",
'/(Debian|Ubuntu)/' => "2.x",
default => "latest",
},
}
NOTE: In the above one has to get the exact name of the OS, i.e. CentOS 7 or CentOS 6 or Ubuntu from each OS. You can do that by executing facter --puppet | grep lsbdistdescription on the OS. I don't have variety of machines, so I couldn't check that exactly.
Then the configuration file can be just one sourced from a template. The template will vary based on the OS.
file { 'file.cfg' :
ensure => "present",
content => template("modulename/file.erb"),
require => Package["syslog-ng"],
}
Hope it helps.

Is this the correct way to change a config file using puppet?

I have a rails app and I'd like to change the ./config/environment/production.rb file to have a different config based on what I want that server to do.
So, I'm going into the .rb file from the .pp file and changing some strings then restarting the service. This just seems really poor form to me. Is there a better way to do this? I've been asked to deliver 1 RPM and change the config via puppet, so...
class Cloud-widget($MServer, $GoogleEarthServer, $CSever) {
package { "Cloud-widget":
ensure => installed
}
service { "Cloud-widget":
ensure => running,
}
<%
file_names = ['./config/environment/production.rb']
file_names.each do |file_name|
puts text.gsub(/.*config.mserver(.*)/, "config.mserver_root = \"#{$Merver}\"")
puts text.gsub(/.*config.google_earth_url(.*)/, "config.google_earth_url( = \"#{$GoogleEarthServer}\"")
puts text.gsub(/.*config.cserver_base_url(.*)/, "config.cserver_base_url = \"#{$CServer}\"")
end
File.open(file_name, "w") {|file| file.puts output_of_gsub}
%>
service { Cloud-widget:
ensure => running,
subscribe => File["./config/environment/production.rb"],
}
}
No, that is not a good way to achieve what you need.
You could look at templates and generate the config files that way. That way, you can use variables in the config file.
If you need create conf from pattern you should use INI-file module from Puppetlabs
ini_setting { "sample setting":
path => '/tmp/foo.ini',
section => 'foo',
setting => 'foosetting',
value => 'FOO!',
ensure => present,
}
install this module from puppet:
puppet module install cprice404-inifile

Resources