Class parameter syntax errors - puppet

I am trying to learn to write puppet modules in a good way, so I've started looking around for tutorials and howto.
I've seen that users suggest writing the main class in the following way, but It's actually failing for me.
I am honestly a bit confused how the 2 blocks between brackets are actually connected, and so I might be not seeing an obvious error or real missing comma.
I am running Puppet 3.8 by the way
class icinga2 {
$version = 'present'
$enable = true
$start = true
} {
class{'icinga2::install': } ->
class{'icinga2::config': } ~>
class{'icinga2::service': } ->
Class["icinga2"]
}
Error: Could not retrieve catalog from remote server: Error 400 on SERVER: Syntax error at '{'; expected '}' at /etc/puppet/modules/icinga2/manifests/init.pp:5

Your problem here is that your parameters must be surrounded by (), not {}. Also, they should be commas separated.
class icinga2 (
$version = 'present',
$enable = true,
$start = true,
) {
class{'icinga2::install': } ->
class{'icinga2::config': } ~>
class{'icinga2::service': } ->
Class["icinga2"]
}

Related

Why are these values sometimes undefined?

I'm fairly new to Perl and am working on a project to further my learning. It's a little console word game (translated from a python project of mine), and part of the logic requires to draw a random letter from a pool that is 98 characters long.
Running the functions individually, I've never had an issue, but when I try to loop it into a list it occasionally fails. Running with warnings on tells me that some of these are undefined, but I can't for the life of me figure out why. Here's an MRE:
package Random;
sub choice {
shift;
my ($str) = #_;
my $random_index = int(rand(length($str)));
return substr($str,$random_index,1); #fixed variable name
}
package Player;
sub new {
my $class = shift;
my $self = { "name" => shift, "letters" => {fillList()} };
bless $self, $class;
return $self;
}
sub drawCharacter {
my $freq = "aaaaaaaaabbccddddeeeeeeeeeeeeffggghhiiiiiiiiijkllllmmnnnnnnooooooooppqrrrrrrssssttttttuuuuvvwwxyyz";
my $choice = Random -> choice($freq);
return $choice;
}
sub fillList {
my #ls = ();
for (0..6) {
push #ls, drawCharacter();
}
return #ls;
}
sub getLetters {
my ($self) = #_;
my $arr = $self -> {letters};
return %$arr;
}
package Main;
my #players = ();
for (0..12){
my $player = Player -> new("Foo");
print($player->getLetters(),"\n");
}
BIG EDIT: Adding the object I'm using. This is verifiably not working. Warnings:
"Use of uninitialized value in print" and "Odd number of elements in anonymous hash". This is where I think the issue lies.
The list returned by fillList sometimes is missing an item or 2, and in some circumstances even 3 or 4 items are missing. Does anybody know what's going on here? The python one hasn't failed once.
If the python analogue would be helpful, I can include that here too.
The error comes from using a hash ref where you should have an array ref:
my $self = { "name" => shift, "letters" => {fillList()} };
# ^ ^-- wrong brackets
This is what the warning talks about:
Odd number of elements in anonymous hash at foo.pl line 22.
You want to change that to:
my $self = { "name" => shift, "letters" => [fillList()] };
# ^ ^--- creates array ref
And also the line which uses this array
return %$arr;
Where you need to change % to #.
return #$arr;
After those fixes, the code runs without errors for me.

puppet defined types and variables

I am new to puppet and I am trying to write a module to manage .bashrc file of 10 users. The following code is ok to manage the file of 1 user. However, I am unable to change the code to manage files for 10 users. I tried using defined types and variable with no luck. Can sombody please suggest me the right way to do this.
init.pp:
class profile (
$bashrc = $profile::params::bashrc,
$bashrc_host = $profile::params::bashrc_host,
) inherits profile::params {
anchor { 'profile::begin': } ->
class { '::profile::config': } ->
anchor { 'profile::end': }
}
config.pp:
class profile::config inherits profile {
file { $bashrc:
ensure => file,
source => "puppet:///$bashrc_host",
}
params.pp:
class profile::params {
$bashrc_host = "modules/profile/$fqdn_user1_bashrc"
}
case $::osfamily {
'RedHat': {
$bashrc = '/home/user1/.bashrc'
}
}
This is not at all a job for a class. As you noted yourself in your most recent comment, this calls for a define actually.
Please don't use verbs in the names of your defines. Instead of defineuser, just do
define profile::user($host_name) {
}
Off the top of my hat, I'm not aware of a good pattern to use module parameters in your defines. You can however use the following pattern:
class profile(
$default_shell = $profile::params::default_shell,
$default_prompt = $profile::params::default_prompt,
$users = {}
) inherits profile::params {
$defaults = { shell => $default_shell, prompt => $default_prompt }
create_resources('profile::user', $users, $defaults)
}
What happens is
values are taken from params, or hiera, or the invoking manifest
these values are gathered in the $defaults array
for any resource in the $users hash that has no shell or prompt, this default is used
If your aim of this module is to learn puppet then:
Add a param user to your class profile::params
class profile::params {
$bashrc_host = "modules/profile/$fqdn_user1_bashrc"
$user = 'user1',
}
case $::osfamily {
'RedHat': {
$bashrc = "/home/$user/.bashrc"
}
}
After this, you can use a combination of array or hiera and ensure_resource This still is not the most elegant solution, but baby steps.
If your intend is to actually manage the bashrc for various users, I would recommend using a pre existing module such as account

Passing variables between classes in puppet

I am trying to use the exec resource type to execute a batch file. But I want to pass the value of variable $dsn_64bit from init.pp to install.pp. Please let me know how to achieve that:
Here is my init.pp
class exec_batchfile ($dsn_64bit = "false")
{
if $::osfamily == 'windows' {
include exec_batchfile::install
}
}
Here is my install.pp
class exec_batchfile::install
{
if $dsn_64bit == true
{
$hklm_path = 'HKLM\Software\Oracle'
$Script_name = 'E:\\Path\\pupp_test64.bat'
}
else
{
$hklm_path = 'HKLM\Software\WOW6432Node\Oracle'
$Script_name = 'E:\\Path\\pupp_test.bat'
}
exec { 'exec_batchfile':
command => "${Script_name}",
path => $::path,
logoutput => true,
unless => "cmd.exe /c reg query ${hklm_path} /v inst_loc",
}
}
Thanks
Since puppet 2.7 dynamic lookup is deprecated, so your code will not work properly. Right now the recommended solution is to use fully qualified names. Please follow the link to find a comprehensive explanation.
Whenever you need to refer to a variable in another class, give the variable an explicit namespace: instead of simply referring to $packagelist, use $git::core::packagelist.

Puppet variable immutability

There is a language pattern I would like to use in puppet and am having trouble figuring out how to implement it. Let's say I have a parameterized class:
class ntp (
$ensure = 'present',
$ntp_package_ensure = 'present',
$ntp_package_name = 'ntp',
$ntp_config_ensure = 'file',
$ntp_config_path = '/etc/ntp.conf',
$ntp_service_ensure = 'running',
$ntp_service_enable = true,
$ntp_service_name = 'ntpd',
) {
I would then really like to be able to say:
if $ensure == 'absent' {
$ntp_package_ensure = 'absent',
$ntp_config_ensure = 'absent',
$ntp_service_ensure = 'stopped',
}
But because puppet variables (constants?) are immutable I'm getting syntax errors. So What is puppets way of doing this? The only solution I can see right now is to add a monolith if statement that partitions the code into an ensure section and an else section.
The most straight forward workaround is to actually introduce new local variables.
case $ensure {
'absent': {
$my_ntp_package_ensure = 'absent'
$my_ntp_config_ensure = 'absent'
$my_ntp_service_ensure = 'stopped'
}
'present': {
...
}
default: {
$my_ntp_package_ensure = $ntp_package_ensure
$my_ntp_config_ensure = $ntp_config_ensure
$my_ntp_service_ensure = $ntp_service_ensure
}
}
Then only use the local counterparts instead of the parameters proper.
I recommend to refrain from such an API design and instead ask a new question concerning the actual scenario and how to structure the ntp module better.

Defining and calling function in puppet 2.6 and 2.7

I have a module core and a class core::logrotate defined in core/manifests/logrotate.pp.
class core::logrotate {
#...some stuff here
#
define confd ($ensure = "present" , $log_name = "dummy" ) {
if ( $ensure == present )
{
file {
"/etc/logrotate.d/$log_name":
ensure => present,
source => filelookup("core/${log_name}.logrotate"),
}
} else {
file {
"/etc/logrotate.d/$log_name":
ensure => absent,
}
}
}
}
calling this function inside of templates.pp as
core::logrotate::confd { "mkill": log_name => mkill }
This fails with the error
Error 400 on SERVER: Puppet::Parser::AST::Resource failed with error ArgumentError: Invalid resource type core::logrotate::confd
If the puppet master version is 2.6.x then this fails, to make it work there used to be a import "*" in the init.pp of the module. Now removed this as moving to puppet 2.7.20.
The code pasted here works in 2.7 but fails in 2.6. Any idea why? how can I make it work for both 2.6 and 2.7?
You should take the define outside of the class, see the style guide: http://docs.puppetlabs.com/guides/style_guide.html#classes
Also, I think that you might be using modules wrong, it would be much more logical to have a 'logrotate' module on its own.
So; in modulepath/logrotate/manifests/confd.pp you'd put this:
define logrotate::confd ($ensure = "present" , $log_name = "dummy" ) {
if ( $ensure == present )
{
file {
"/etc/logrotate.d/$log_name":
ensure => present,
source => filelookup("core/${log_name}.logrotate"),
}
} else {
file {
"/etc/logrotate.d/$log_name":
ensure => absent,
}
}
}
That should make it work properly.
Greetings,
Ger

Resources