Puppet : how to resolve "file_line" multi match patterns - puppet

I'm trying to change configuration file using puppet.
This is my test.txt file that i want to change :
[default]
#puppet=no
abc=123
[nova]
#puppet=no
I want to change "#puppet=no" to "puppet=yes" only on [default] tab.
This is my test.pp for two version :
file_line{"someline":
path => '/root/openstack-puppet/computenode/nova/test.txt',
match => '[default]\n#puppet',
line => 'puppet=ok'
}
This one failed to find match pattern, so it just add "puppet=ok" at the end of file.
file_line{"someline":
path => '/root/openstack-puppet/computenode/nova/test.txt',
match => '#puppet',
line => 'puppet=ok'
}
This one failed because of multi match pattern problem.
I tried Augeas also, but I can't find how to uncomment using Augeas.
Somebody please help me with this problem!!
=========================================================================
I run this code :
file_line { 'someline':
path => '/root/openstack-puppet/computenode/nova/test.txt',
after => '\[default\]',
multiple => 'false',
match => '#puppet',
line => 'puppet=ok',
}
But when I run with "puppet apply" it still makes same error :
Error: More than one line in file '/root/openstack-puppet/computenode/nova/test.txt' matches pattern '#puppet'
Error: /Stage[main]/Main/File_line[someline]/ensure: change from absent to present failed: More than one line in file '/root/openstack-puppet/computenode/nova/test.txt' matches pattern '#puppet'
I think that 'after' attribute cannot applied when 'match' attribute is defined.
When I erase 'match' attribute, it works, but it didn't replace original string('#puppet=no').
It just added new line after [default] like this :
[default]
puppet=ok
#puppet=no
abc=123
dedd=0
[nova]
#puppet=no
So the issues still remain, how can I erase(or replace) the string '#puppet=no'
only on [default] tab??

The after attribute will solve this problem for you. Taking your second resource and cleaning up some, we have:
file_line { 'someline':
path => '/root/openstack-puppet/computenode/nova/test.txt',
match => '#puppet',
line => 'puppet=ok'
after => '[default]',
multiple => false,
}
Notice I also added the multiple attribute to safeguard against changing more than just the line you want to change.
The reason your first resource would have issues is threefold. First, file_line requires that your line attribute have a successful regexp match against the match attribute, which is not true in your case. Second, putting [default] in the match attribute means that [default] would be removed from your file if the resource succeeded as you wrote it. Third, you need to escape [] in your regexp, so it would look like \[default\] if you wanted to go that route (and you do not for the first two reasons given).

The file looks like it fits with the ini file format so a better solution would be to use the inifile resource type https://forge.puppet.com/modules/puppetlabs/inifile
ini_setting { "sample setting":
ensure => present,
path => '/root/openstack-puppet/computenode/nova/test.txt',
section => 'default',
setting => 'puppet',
value => 'yes',
}

Hi you can try it.
include stdlib
file_line{"someline":
ensure => 'present',
after => 'default',
multiple => false,
path => '/root/openstack-puppet/computenode/nova/test.txt',
line => 'puppet=ok',
}

Related

Injecting facter into file content - no implicit conversion of Hash into String

I want to inject some values from facter <prop> into a file content.
It works with $fqdn since facter fqdn returns string.
node default {
file {'/tmp/README.md':
ensure => file,
content => $fqdn, # $(facter fqdn)
owner => 'root',
}
}
However, it does not work with hash object (facter os):
node default {
file {'/tmp/README.md':
ensure => file,
content => $os, # $(facter os) !! DOES NOT WORK
owner => 'root',
}
}
And getting this error message when running puppet agent -t:
Error: Failed to apply catalog: Parameter content failed on
File[/tmp/README.md]: Munging failed for value
{"architecture"=>"x86_64", "family"=>"RedHat", "hardware"=>"x86_64",
"name"=>"CentOS", "release"=>{"full"=>"7.4.1708", "major"=>"7",
"minor"=>"4"}, "selinux"=>{"config_mode"=>"enforcing",
"config_policy"=>"targeted", "current_mode"=>"enforcing",
"enabled"=>true, "enforced"=>true, "policy_version"=>"28"}} in class
content: no implicit conversion of Hash into String (file:
/etc/puppetlabs/code/environments/production/manifests/site.pp, line:
2)
How to convert the hash to string inside the pp file?
If you have Puppet >= 4.5.0, it is now possible to natively convert various data types to strings in the manifests (i.e. in the pp files). The conversion functions are documented here.
This would do what you want:
file { '/tmp/README.md':
ensure => file,
content => String($os),
}
or better:
file { '/tmp/README.md':
ensure => file,
content => String($facts['os']),
}
On my Mac OS X, that leads to a file with:
{'name' => 'Darwin', 'family' => 'Darwin', 'release' => {'major' => '14', 'minor' => '5', 'full' => '14.5.0'}}
Have a look at all that documentation, because there are quite a lot of options that might be useful to you.
Of course, if you wanted the keys inside the $os fact,
file { '/tmp/README.md':
ensure => file,
content => $facts['os']['family'],
}
Now, if you don't have the latest Puppet, and you don't have the string conversion functions, the old way of doing this would be via templates and embedded Ruby (ERB), e.g.
$os_str = inline_template("<%= #os.to_s %>")
file { '/tmp/README.md':
ensure => file,
content => $os_str,
}
This actually leads to a slightly differently-formatted Hash since Ruby, not Puppet does the formatting:
{"name"=>"Darwin", "family"=>"Darwin", "release"=>{"major"=>"14", "minor"=>"5", "full"=>"14.5.0"}}

file_line appends data on every puppet run

file_line { '/etc/profile.d/setjvmparams.sh':
path => '/etc/profile.d/setjvmparams.sh',
line => "export JAVA_HOME=/usrdata/apps/java/${tomcat::jdkversion}\nexport JRE_HOME=/usrdata/apps/java/${tomcat::jdkversion}/jre\nexport PATH=\"/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:\$JAVA_HOME/bin\"",
}
This is appending the data each time. As far as I read, file_line was designed to add data only if it did not exist in the file. How to make sure, it gets added only when not present?
The file_line type should be used for single lines, but the line parameter you're passing has three lines separated with \n. This should be split into three resources:
file_line { '/etc/profile.d/setjvmparams.sh JAVA_HOME':
path => '/etc/profile.d/setjvmparams.sh',
line => "export JAVA_HOME=/usrdata/apps/java/${tomcat::jdkversion}",
}
file_line { '/etc/profile.d/setjvmparams.sh JRE_HOME':
path => '/etc/profile.d/setjvmparams.sh',
line => "export JRE_HOME=/usrdata/apps/java/${tomcat::jdkversion}/jre",
}
file_line { '/etc/profile.d/setjvmparams.sh PATH':
path => '/etc/profile.d/setjvmparams.sh',
line => "export PATH=\"/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:\$JAVA_HOME/bin\"",
}

logstash pattern don't match in the expected way

I'm using logstash to collect my server.log from several glassfish domains. Unfortunatly in the log is no domainname. But the pathname have.
So I tried to get a part of the filename to match it to the GF-domain. The Problem is, that the pattern I defined don't matche the right part.
here the logstash.conf
file {
type => "GlassFish_Server"
sincedb_path => "D:/logstash/.sincedb_GF"
#start_position => beginning
path => "D:/logdir/GlassFish/Logs/GF0/server.log"
}
grok {
patterns_dir => "./patterns"
match =>
[ 'path', '%{DOMAIN:Domain}']
}
I' ve created a custom-pattern file and filled it with a regexp
my custom-pattern-file
DOMAIN (?:[a-zA-Z0-9_-]+[\/]){3}([a-zA-Z0-9_-]+)
And the result is:
"Domain" => "logdir/GlassFish/Logs/GF0"
I've tested my RegExp on https://www.regex101.com/ and is working fine.
Using http://grokdebug.herokuapp.com/ to verify the pattern brings the same "unwanted" result.
What I'm doing wrong? Has anybody an idea to get only the domain name "GF0", e.g. modify my pattern or using mutate in the logstash.conf?
I'm assuming that you're trying to strip out the GF0 portion from path?
If that's the case and you know that the path will always be in the same format, you could just use something like this for the grok:
filter {
grok {
match => [ 'path', '(?i)/Logs/%{WORD:Domain}/' ]
}
}
not as elegant as a regexp, but it should work.

logstash : file input is not working

I am trying to run sample eg. using logstash-1.4.2 in CDH 4.4. Whenever I use file input instead of stdin, the window freezes at the following message:
Using milestone 2 plugin 'file'. This plugin should be stable but if
you see strange behavior, please let us know! For more
information.....
My code looks like this:
input {
file {
path => "/tmp/access_log"
start_position => "beginning"
}
}
filter {
if [path] =~ "access" {
mutate { replace => { "type" => "apache_access" } }
grok {
match => { "message" => "%{COMBINEDAPACHELOG}" }
}
}
date {
match => [ "timestamp" , "dd/MMM/yyyy:HH:mm:ss Z" ]
}
}
output {
file{
path =>"/logs/output_log"
}
}
Command- bin/logstash -f logstash-apache.conf
I have tried deleting all my previous sincedb files in the $HOME. directory and re-run logstash, but that doesn't seem to work either. Am I missing something?
if you have just one line in your input file,
you should add an empty line at the end!
that should work!
edited:
AND if you are on a windows machine, you need to write the absolute path like
"c:/dev/access-log.txt"
and take care of just using one / instead of // after the c:
I got stuck because logstash tracks which logs it has already read: https://stackoverflow.com/a/24034718/268907
Remember that this option only modifies “first contact” situations where a file is new and not seen before. If a file has already been seen before, this option has no effect. Otherwise you have to set your sincedb_path to /dev/null .
Set sincedb_path to /dev/null and you will prevent it from tracking the position in the file that it last read.
Are you running with root permissions? It looks like /logs/output_log needs root permission to be written to.
I tried your configuration locally with logstash 1.4.1 (and sudo) and it seems to be working fine.
Could you try the below one. It worked for me.
path => "/tmp/access_log/*"
instead of
path => "/tmp/access_log"

puppet chown/chmod against files under a directory in batch

In puppet, you can chown/chmod a single file by doing:
file {
'/var/log/mylog/test.log':
ensure => 'present',
mode => '0644',
owner => 'me';
}
Two questions on this:
ensure=>'present' is gonna make sure '/var/log/mylog/test.log' exists, if it doesn't it creates it. Is there any way I can make it do actions if file exists, if file doesn't exist, don't bother to create/delete it, just ignore it and carry on.
Let's say I have 3 files under /var/log/mylog/, I want to chown/chmod against them all in a batch instead of having 3 file resource sections in my puppet code. Can I do something like below(of coz, the code below doesn't exist, it's in my dream now ^_^ ):
files {
'/var/log/mylog/*.log':
ensure => 'present',
mode => '0644',
owner => 'me';
}
If you want to specify to take a given action if file exists, if file doesn't exist etc. you have no choice (to my knownledge) currently than to use the exec resource with creates + onlyif or unless directives.
You could use for instance (see reference doc)
exec { "touch /var/log/mylog/test.log":
path => "/usr/bin:/usr/sbin:/bin",
user => "${yourmodule::params::user}",
group => "${yourmodule::params::group}",
creates => "/var/log/mylog/test.log",
unless => "test -f /var/log/mylog/test.log"
}
file { '/var/log/mylog/test.log':
ensure => 'present',
mode => "${${yourmodule::params::mode}",
owner => "${yourmodule::params::user}",
group => "${yourmodule::params::group}",
require => Exec["touch /var/log/mylog/test.log"]
}
No. Again, you'll have to use an execresource.

Resources