Only classes can set 'stage'; normal resources like XXX cannot change run stage - puppet

I have a manifest where a package depends on an apt::source resource. I've tried to make sure the apt::source runs first by setting a stage:
include apt
stage { 'first':
before => Stage['main']
}
apt::source { 'erlang_repo':
location => 'http://packages.erlang-solutions.com/ubuntu',
repos => 'contrib',
key => 'A14F4FCA',
stage => first
}
package { 'erlang':
ensure => '1:17.3'
}
However, I'm hitting the following error:
==> default: Error: Puppet::Parser::AST::Resource failed with error ArgumentError: Only classes can set 'stage'; normal resources like Apt::Source[erlang_repo] cannot change run stage at /tmp/manifests/default.pp:12 on node vagrant-ubuntu-trusty-64.home
==> default: Wrapped exception:
==> default: Only classes can set 'stage'; normal resources like Apt::Source[erlang_repo] cannot change run stage
==> default: Error: Puppet::Parser::AST::Resource failed with error ArgumentError: Only classes can set 'stage'; normal resources like Apt::Source[erlang_repo] cannot change run stage at /tmp/manifests/default.pp:12 on node vagrant-ubuntu-trusty-64.home
Any pointers will be appreciated.

If you really want to use stages, you should wrap the appropriate resources in (possibly dedicated) classes.
class site::apt_sources {
apt::source { ... }
}
and declare it like
class { 'site::apt_sources': stage => first }
Please note that the use of stages is discouraged.
If you don't use virtual resources, you can probably achieve the desired effect through this relationship instead:
Apt::Source<| |> -> Package<| |>

I decided to go with this in the end:
include apt
Apt::Pin <| |> -> Package <| |>
Apt::Source <| |> -> Package <| |>
apt::source { 'erlang_repo':
location => 'http://packages.erlang-solutions.com/ubuntu',
repos => 'contrib',
key => 'A14F4FCA'
}
package { 'erlang':
ensure => '1:17.3',
}

Related

Creating master and slaves DNS with puppet module camptocamp bind

Trying to create a master and slave (redundancy) DNS with puppet module camptocamp bind. In slave profile, I've set transfer_source => '192.168.1.20' to masters ip: 192.168.1.20. It should then synchronize and copy dns records from master to the slave.
But I got complaints about that it could only be set to slave zones. I've followed the README from puppet forge for the module: https://forge.puppet.com/camptocamp/bind/readme
dnsmaster.pp
class profile::dnsbind::server {
include 'bind'
bind::zone {'example.com':
ensure => 'present',
zone_contact => 'contact.example.com',
zone_ns => ['ns0.example.com'],
zone_serial => '2012112901',
zone_ttl => '604800',
zone_origin => 'example.com',
}
bind::a { 'example.com':
ensure => 'present',
zone => 'example.com',
ptr => false,
hash_data => {
'host1' => { owner => '192.168.0.1', },
'host2' => { owner => '192.168.0.2', },
},
}
}
dnsslave.pp
class profile::dnsbind::server_slave {
include 'bind'
bind::zone {'example.com':
ensure => 'present',
zone_contact => 'contact.example.com',
zone_ns => ['ns0.example.com'],
zone_serial => '2012112901',
zone_ttl => '604800',
zone_origin => 'example.com',
transfer_source => '192.168.1.20',
}
}
The error message:
Error: Could not retrieve catalog from remote server: Error 500 on SERVER: Server Error: Evaluation Error: Error while evaluating a Resource Statement, Evaluation Error: Error while evaluating a Function Call, Zone 'example.com': transfer_source can be set only for slave zones! at /etc/puppetlabs/code/environments/production/modules/bind/manifests/zone.pp:80:5 at /etc/puppetlabs/code/environments/production/manifests/profile_dns2.pp:5 on node centos7-3
Warning: Not using cache on failed catalog
Error: Could not retrieve catalog; skipping run
It should then synchronize and copy dns records from master to the
slave.
But I got complaints about that it could only be set to slave zones.
Evidently, the module does not recognize that you're trying to configure a slave zone. How do you suppose it would know? Well, apparently not from the presence of a transfer_source property.
I've followed the README from puppet forge for the module:
https://forge.puppet.com/camptocamp/bind/readme
I'll believe that you started by pulling the example zone definition (for a master zone) from the readme, and I grant you that this module's docs are kinda shoddy. But do nevertheless consider actually reading the docs thoroughly, not just skimming them. If you had done, you would have found documentation for the zone_type parameter immediately following the the documentation for the transfer_source parameter:
$zone_type = master
Specify if the zone is master/slave/forward.
Use this to specify that you're configuring a slave zone.

Puppet can't find class firewall

I have a basic puppet install using this tutorial https://www.digitalocean.com/community/tutorials/how-to-install-puppet-4-on-ubuntu-16-04
When I run /opt/puppetlabs/bin/puppet agent --test on my node I get
Error: Could not retrieve catalog from remote server: Error 500 on SERVER: Server Error: Error while evaluating a Resource Statement. Could not find declared class firewall at /etc/puppetlabs/code/environments/production/manifests/site.pp:7:1 on node mark-inspiron.
On my node:
/opt/puppetlabs/bin/puppet module list
returns
/etc/puppetlabs/code/environment/production/modules
----- puppetlabs-firewall (v1.9.0)
On my puppet master at /etc/puppetlabs/code/environments/production/manifests/site.pp:
file {'/tmp/it_works.txt': # resource type file and filename
ensure => present, # make sure it exists
mode => '0644', # file permissions
content => "It works on ${ipaddress_eth0}!\n", # Print the eth0 IP fact
}
class { 'firewall': }
resources { 'firewall':
purge => true,
}
firewall { "051 asterisk-set-rate-limit-register":
string => "REGISTER sip:",
string_algo => "bm",
dport => '5060',
proto => 'udp',
recent => 'set',
rname => 'VOIPREGISTER',
rsource => 'true';
}
firewall { "052 asterisk-drop-rate-limit-register":
string => "REGISTER sip:",
string_algo => "bm",
dport => '5060',
proto => 'udp',
action => 'drop',
recent => 'update',
rseconds => '600',
rhitcount => '5',
rname => 'VOIPREGISTER',
rsource => true,
rttl => true;
}
The file part works but not firewall.
You need to install the modules on your master in a master setup with Puppet. They need to be somewhere in your modulepath. You can either place it in the modules directory within your $codedir (normally /etc/puppetlabs/code/modules) or in your directory environment modules directory (likely /etc/puppetlabs/code/environments/production/modules in your case since your cited site.pp is there). If you defined additional module paths in your environment.conf, then you can also place the modules there.
You can install/deploy them with a variety of methods, such as librarian-puppet, r10k, or code-manager (in Enterprise). However, the easiest method for you would be puppet module install puppetlabs-firewall on the master. Your Puppet catalog will then find the firewall class during compilation.
On a side note, that:
resources { 'firewall':
purge => true,
}
will remove any changes to associated firewall configurations (as defined by Puppet's knowledge of the system firewall configuration according to the module's definition of what the resource manages) that are not managed by Puppet. This is nice for eliminating local changes that people make, but it can also have interesting side effects, so be careful.

Containing a defined resource type in Puppet

I'm trying to create an instance of a defined resource type (::apt::ppa) that comes before other resources. I am using the PuppetLabs Apt Module.
When adding a new repository via the module, the defined type contains an exec statement that notifies apt::update so that any packages that might be required can be installed correctly. However, when I run my below code, the notify gets scheduled after I attempt to install Java, thereby causing the Java install to fail. I've tried putting anchors around the apt::ppa declaration, but that doesn't help. What else can I do?
class rap::java(
$version = '7',
) {
$package = "oracle-java${version}-installer"
apt::ppa { 'ppa:webupd8team/java': } ->
exec { 'accept-java-license':
command => "/bin/echo ${package} shared/accepted-oracle-license-v1-1 select true | /usr/bin/sudo /usr/bin/debconf-set-selections",
unless => "/usr/bin/debconf-show ${package} | grep 'shared/accepted-oracle-license-v1-1: true'",
} ->
class { '::java':
package => $package,
distribution => 'oracle-jre',
}
file_line { 'java_environment':
path => '/etc/environment',
line => "JAVA_HOME=\"/usr/lib/jvm/java-${version}-oracle\"",
}
}
I believe the issue is that you need to include the apt class within the class you've made to get the ordering right.
This works for me on a new Precise box:
class rap::java(
$version = '7',
) {
$package = "oracle-java${version}-installer"
include apt
apt::ppa { 'ppa:webupd8team/java':
package_manage => true,
}
exec { 'accept-java-license':
command => "/bin/echo ${package} shared/accepted-oracle-license-v1-1 select true | /usr/bin/sudo /usr/bin/debconf-set-selections",
unless => "/usr/bin/debconf-show ${package} | grep 'shared/accepted-oracle-license-v1-1: true'",
}
class { '::java':
package => $package,
distribution => 'oracle-jre',
require => [
Apt::Ppa['ppa:webupd8team/java'],
Exec["accept-java-license"],
]
}
file_line { 'java_environment':
path => '/etc/environment',
line => "JAVA_HOME=\"/usr/lib/jvm/java-${version}-oracle\"",
}
}
Log of run:
Notice: Compiled catalog for precise64 in environment production in 0.78 seconds
Notice: /Stage[main]/Apt/File[preferences]/ensure: created
Notice: /Stage[main]/Rap::Java/Exec[accept-java-license]/returns: executed successfully
Notice: /Stage[main]/Rap::Java/File_line[java_environment]/ensure: created
Notice: /Stage[main]/Apt/Apt::Setting[conf-update-stamp]/File[/etc/apt/apt.conf.d/15update-stamp]/ensure: defined content as '{md5}0962d70c4ec78bbfa6f3544ae0c41974'
Notice: /Stage[main]/Rap::Java/Apt::Ppa[ppa:webupd8team/java]/Package[python-software-properties]/ensure: created
Notice: /Stage[main]/Rap::Java/Apt::Ppa[ppa:webupd8team/java]/Exec[add-apt-repository-ppa:webupd8team/java]/returns: executed successfully
Notice: /Stage[main]/Apt::Update/Exec[apt_update]: Triggered 'refresh' from 1 events
Notice: /Stage[main]/Java/Package[java-common]/ensure: created
Notice: /Stage[main]/Java/Package[java]/ensure: created
Notice: Applied catalog in 39.58 seconds
To extend the question further, generally things that are blockers for a standard setup to run are usually moved into a run stage (documented here).
So I would probably move all of the various repo setup puppet code into pre run stage with other prerequisites (normally you put in repo setup), the run stage will always be run first before the main stage, so you don't have to worry about explictly setting requirements that repos are setup on each package. This makes making changes to repos and prerequisites a lot easier

Puppet. Using define with 2 variables

I have config file /home/ipeacocks/Dropbox/nscd/nscd.conf:
$ cat home/ipeacocks/Dropbox/nscd/nscd.conf
logfile /var/log/nscd.log
threads 4
max-threads 32
server-user nobody
stat-user somebody
debug-level 0
reload-count 5
paranoia no
restart-interval 3600
With puppet I want to change 2 lines:
server-user nobody
paranoia no
To these lines:
server-user nscd
paranoia yes
So for changing one first line I can use such manifest:
include nscd
class nscd {
define line_replace ($line, $match) {
file_line {'some useful info':
path => '/home/ipeacocks/Dropbox/nscd/nscd.conf',
line => $line,
match => $match
}
}
anchor{'nscd::begin':}
->
package { 'nscd':
ensure => installed,
}
->
line_replace {'test':
line => "server-user nscd",
match => "^\s*server-user.*$"
}
->
service { 'nscd':
ensure => running,
enable => "true",
}
->
anchor{'nscd::end':}
}
Puppet launch:
» sudo puppet apply /home/ipeacocks/Dropbox/nscd/nscd.pp
Notice: Compiled catalog for softserve-pc.ddns.softservecom.com in environment production in 0.37 seconds
Notice: /Stage[main]/Nscd/Nscd::Line_replace[test]/File_line[some useful info]/ensure: created
Notice: Finished catalog run in 0.22 seconds
But cant when 2 lines (using declared function twice):
include nscd
class nscd {
define line_replace ($line, $match) {
file_line {'some useful info':
path => '/home/ipeacocks/Dropbox/nscd/nscd.conf',
line => $line,
match => $match
}
}
anchor{'nscd::begin':}
->
package { 'nscd':
ensure => installed,
}
->
line_replace {'test':
line => "server-user nscd",
match => "^\s*server-user.*$"
}
->
line_replace {'test2':
line => "paranoia yes",
match => "^\s*paranoia.*$"
}
->
service { 'nscd':
ensure => running,
enable => "true",
}
->
anchor{'nscd::end':}
}
Launching again:
» sudo puppet apply /home/ipeacocks/Dropbox/nscd/nscd.pp 1 ↵
Error: Duplicate declaration: File_line[some useful info] is already declared in file /home/ipeacocks/Dropbox/nscd/nscd.pp:10; cannot redeclare at /home/ipeacocks/Dropbox/nscd/nscd.pp:10 on node softserve-pc.ddns.softservecom.com
Error: Duplicate declaration: File_line[some useful info] is already declared in file /home/ipeacocks/Dropbox/nscd/nscd.pp:10; cannot redeclare at /home/ipeacocks/Dropbox/nscd/nscd.pp:10 on node softserve-pc.ddns.softservecom.com
What can be wrong? Is it possible to pass two pairs of vars to declared function at once (with arrays or like that)?
I have tried this solution but it doesn't work for me:
https://stackoverflow.com/a/19034077/2971192
Change the 'some useful info' to $name in file_line -
define line_replace ($line, $match) {
file_line {$name:
path => '/home/ipeacocks/Dropbox/nscd/nscd.conf',
line => $line,
match => $match
}
}
The problem you are facing is because the second call to line_replace causes call to file_line with resource name 'some useful info' which is already declared.
Replace your define with this:
define line_replace ($line, $match) {
file_line {$name:
path => '/home/ipeacocks/Dropbox/nscd/nscd.conf',
line => $line,
match => $match
}
}
I changes the file_line resource name from a constant to the $name parameter of your define.

Puppet Exec what "<| |>" means?

I'm learning puppet language and noticed one very intriguing line of code: Exec["apt-update"] -> Package <| |> on following context:
class manifest::module {
exec { "apt-update":
command => "/usr/bin/apt-get -y update",
timeout => 3600;
}
package {
["alien", "bc", "libaio1", "unixodbc", "unzip", "rlwrap"]:
ensure => installed;
}
Exec["apt-update"] -> Package <| |>
}
Why Exec is followed by the ->? And most important, what's the meaning of <| |> ???
This expression essentially instructs Puppet to have any package resource require the "apt-update" exec resource. In other words Puppet will be sure to execute apt-get update before installing/purging/... a package.
It matches any package, see http://docs.puppetlabs.com/puppet/latest/reference/lang_collectors.html for more details

Resources