I used to just include all of my puppet modules like so:
include user_manager
include pp_package_manager
include ppcc_code_manager
include ppcc_backup
include pp_db_manager
include pp_apache_manager
include pp_rabbit_manager
include pp_salt_manager
include pp_freeswitch_manager
include ppcc_services_manager
This caused lots of dependency problems and I had to run the puppet agent multiple times before they would all resolve themselves. I then tried using Stages to clean that up, resulting in this:
stage { 'code': require => Stage['main'], before => Stage['backup'], }
stage { 'backup': before => Stage['big-packages'], }
stage { 'big-packages': before => Stage['freeswitch'], }
stage { 'freeswitch': before => Stage['services'] }
stage { 'services': }
node 'blah.example.com' {
class { 'pp_package_manager': stage => 'main', }
class { 'user_manager': stage => 'main', }
class { 'ppcc_code_manager': stage => 'code', }
class { 'ppcc_backup': stage => 'backup', }
class { 'pp_db_manager': stage => 'big-packages', }
class { 'pp_apache_manager': stage => 'big-packages', }
class { 'pp_rabbit_manager': stage => 'big-packages', }
class { 'ppcc_services_manager': stage => 'services', }
class { 'pp_salt_manager': stage => 'big-packages', }
class { 'pp_freeswitch_manager': stage => 'freeswitch', }
}
I even tried putting everything in the node definition, using arrow notation, defining the stages before and then using arrow notations. Each time, nothing happened. No errors, just nothing. Even using --debug, the puppet agent would just... stop.
Finally, I just tried using arrow notations between each of the class declarations.
class { 'user_manager': } ->
class { 'pp_package_manager': } ->
class { 'ppcc_code_manager': } ->
class { 'ppcc_backup': } ->
class { 'pp_db_manager': } ->
class { 'pp_apache_manager': } ->
class { 'pp_rabbit_manager': } ->
class { 'pp_salt_manager': } ->
class { 'pp_freeswitch_manager': } ->
class { 'ppcc_services_manager': }
That didn't run either. I'm pretty much all out of ideas now. Why is nothing happening when I run the puppet agent? What am I doing wrong?
I can't really comment on the issues without seeing what your manifests look like.
But I think there is something that could help you: Have you read about the roles and profiles pattern? It helps with these kind of design issues and helps narrowing down which manifests are causing problems.
It also allows you to apply testing to each component or group of components, so you can narrow down what the issue is that's causing the agent not to run.
Some example posts about it here:
https://puppetlabs.com/presentations/designing-puppet-rolesprofiles-pattern
http://garylarizza.com/blog/2014/02/17/puppet-workflow-part-2/
http://rnelson0.com/2014/07/14/intro-to-roles-and-profiles-with-puppet-and-hiera/
Related
I decided to use #CheckReturnValue annotation to make sure, that in my code I always subscribe to the flowable object. But I noticed that in some cases it doesn't work. This looks like a Lint problem, but maybe I do smth wrong or don't get smth.
Method being called.
#CheckReturnValue
fun insertTask(task: Groupie): Completable = Completable.fromAction { dao.insertTask(task) }
.subscribeOn(Schedulers.io())
Code that calls the method:
fun test(g: Groupie, obj: Any) {
db.insertTask(g) // 1.
when (obj) {
is WebSocketMessage.GroupieUpdate -> {
subs.add(db.getTask(g.id).map { oldGroupie -> g.copy(text = oldGroupie.text) }
.subscribe(
{ t -> db.insertTask(t) }, // 2.
::onError
)
)
db.insertTask(g) // 3.
}
}
}
QUESTION: Why exactly 1st call is marked as wrong by Lint in Android Studio, but 2nd and 3rd are not?
RxJava v2.2.19
Android Studio v3.6.1
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
Trying to do something like this:
# nodes.pp
node 'dev-a-1.sn1.vpc1.example.com' inherits project_j1n_sn1_vpc1_dev {
class { 'custom::core':
overrides => {
'openssh' => {'settings' => {'external_access' => 'true'}}, # Allow direct mounting for dev
'rsyslog' => {'settings' => {'role' => 'node', 'filters' => {'php' => {'target' => 'remote'}, 'mail' => {'target' => 'remote'}}}}
}
}
}
# custom::core
class custom::core($overrides = {}) {
if (has_key($overrides, 'openssh')) {
$settings = $overrides['openssh']['settings']
# Doesn't work
create_resources('openssh', $settings)
# Doesn't work
class { 'openssh': $settings }
}
}
Is it possible to call a class and pass a hash as the arguments?
Puppet/Puppetmaster v2.7.26-1 (Centos 6.7)
There is a way in Puppet 4+.
class { 'ssh':
* => $settings
}
Learn all about it on roidelapluie's blog.
A co-worker of mine had come up with a good solution to something similar in the old 2+ days of puppet. Utilized create_resources for this.
http://www.followski.com/quick-note-how-to-use-create_resources-to-initialize-a-class-in-puppet/
your code can look something like this:
nodes.pp
node 'dev-a-1.sn1.vpc1.example.com' inherits project_j1n_sn1_vpc1_dev {
class { 'custom::core':
overrides => {
'openssh' => {'settings' => {'external_access' => 'true'}}, # Allow direct mounting for dev
'rsyslog' => {'settings' => {'role' => 'node', 'filters' => {'php' => {'target' => 'remote'}, 'mail' => {'target' => 'remote'}}}}
}
}
}
custom::core
class custom::core($overrides = {}) {
if (has_key($overrides, 'openssh')) {
$settings = $overrides['openssh']['settings']
create_resources('class', { 'openssh' => $settings })
}
}
You will notice that in the example linked above it looks like create_resources('class', $params), but that assuming you have a hash with a key being the class name (ie openssh) and its value being the params to set. The example I state above essentially does the same thing.
Your node definition can also be look like this:
node 'dev-a-1.sn1.vpc1.example.com' inherits project_j1n_sn1_vpc1_dev {
class { 'custom::core':
overrides => {
'openssh' => {'external_access' => 'true'}, # Allow direct mounting for dev
'rsyslog' => {'role' => 'node', 'filters' => {'php' => {'target' => 'remote'}, 'mail' => {'target' => 'remote'}}}
}
}
}
and your class something like this:
class custom::core($overrides = {}) {
if (has_key($overrides, 'openssh')) {
create_resources('class', {'openssh' => $overrides['openssh'])
}
if (has_key($overrides, 'rsyslog')) {
create_resources('class', {'rsyslog' => $overrides['rsyslog'])
}
}
I think you get the point by now.
We used this quite often a few years ago. You may want to consider moving towards an upgrade of your puppet infrastructure however.
Hope this helps, or at least points you in the right direction.
This post refers to Puppet "require" not working as expected.
Is it possible to replace the Anchor Pattern with the function contain maintaining execution order and hinder declared classes of floating out. The two manifests look as follows:
class profile::maven inherits profile::base {
# Hiera
$version = hiera('profile::maven::version', '3.2.1')
$settings = hiera_hash('profile::maven::settings', undef)
$environments = hiera_hash('profile::maven::environments', undef)
include 'profile::java'
anchor { 'profile::maven::begin': }
class { '::maven::maven': version => $version, }
anchor { 'profile::maven::end': }
if ($settings) {
create_resources('::maven::settings', $settings)
}
if ($environments) {
create_resources('::maven::environment', $environments)
}
Anchor['profile::maven::begin'] -> Class['profile::java'] -> Class['::maven::maven'] -> Anchor['profile::maven::end']
}
and
class profile::java inherits profile::base {
# Hiera
$distribution = hiera('profile::java::distribution', 'jdk')
$version = hiera('profile::java::version', 'present')
anchor { 'profile::java::begin': }
class { '::java':
distribution => $distribution,
version => $version,
}
anchor { 'profile::java::end': }
# Parameters
$java_home = $::java::java_home
file { 'profile-script:java.sh':
ensure => present,
path => '/etc/profile.d/java.sh',
content => template('profile/java.sh.erb'),
}
Anchor['profile::java::begin'] -> Class['::java'] -> File['profile-script:java.sh'] -> Anchor['profile::java::end']
}
Because of the current issue PUP-1597 in Puppet 3.6.x, the profile classes have to be renamed, otherwise we get Error: undefined method 'ref' for nil:NilClass. Applying the changes result in:
class profile::mavenp inherits profile::base {
# Hiera
$version = hiera('profile::maven::version', '3.2.1')
$settings = hiera_hash('profile::maven::settings', undef)
$environments = hiera_hash('profile::maven::environments', undef)
include 'profile::javap'
class { '::maven::maven': version => $version, }
contain 'maven::maven'
if ($settings) {
create_resources('::maven::settings', $settings)
}
if ($environments) {
create_resources('::maven::environment', $environments)
}
Class['profile::javap'] -> Class['::maven::maven']
}
and
class profile::javap inherits profile::base {
# Hiera
$distribution = hiera('profile::java::distribution', 'jdk')
$version = hiera('profile::java::version', 'present')
class { '::java':
distribution => $distribution,
version => $version,
}
contain 'java'
# Parameters
$java_home = $::java::java_home
file { 'profile-script:java.sh':
ensure => present,
path => '/etc/profile.d/java.sh',
content => template('profile/java.sh.erb'),
}
}
Are these changes equivalent?
If someone has a better idea of how to the deal with technologcial dependencies in Puppet using the profile/role approach, do not hesitate to share your thoughts.
The latter pair of classes are not completely equivalent equivalent to the former. The biggest issue is in profile::javap. Note that its analog profile::java has this as part of its dependency chain:
Class['::java'] -> File['profile-script:java.sh']
Class profile::javap has no analog of that.
I'm not 100% certain whether class profile::mavenp is equivalent to class profile::maven, though I think it is. Your intent would be clearer and my uncertainty would be resolved if the former included
contain 'profile::javap'
instead of (or in addition to)
include 'profile::javap'
Let's say for example I have 3 servers, those 3 servers has apache installed.
For each of them I have to instantiate several apache::vhost defined resource.
Is there any way that instead of doing that
node 'srv1.example.com' inherit webserver {
apache::vhost { 'toto1' :
... => ... ,
}
apache::vhost { 'toto2' :
... => ... ,
}
apache::vhost { 'toto3' :
... => ... ,
}
}
One can do something with the following pattern (admitting that my defined resource just with the name can do what it needs to)
node 'srv1.example.com' inherit webserver {
$vhost = ['toto1', 'toto2', 'toto3'];
??????
}
Yes.
node 'srv1.example.com' inherit webserver {
$vhosts = ['toto1', 'toto2', 'toto3'];
apache::vhost { [$vhosts]:
... => ... ,
}
}
This, of course, requires that everything be the same or be based on the name (which is available as $name inside the apache::vhost define).
If you want to keep apache::vhost as a straightforward define and still do some more complicated things to work out parameters from the name, you can do them with an intermediate define:
define blah::vhost {
$wwwroot = "/var/www/html/blah/${name}"
$wwwhostname = "${name}.example.com"
if ! defined(File[$wwwroot]) {
file { $wwwroot:
ensure => directory,
mode => 0775,
}
}
apache::vhost { $name:
path => $wwwroot,
aliases => [$name],
hostname => $wwwhostname,
require => File[$wwwroot],
}
}
blah::vhost { [$vhosts]: }