Puppet: is there a way to catch failure to apply a resource? - puppet

is there a way in Puppet to catch a failure when resource is applied, for example, when declaration like
file { '/var/tmp/test':
ensure => file,
mode => '0755',
}
fails, invoke something like
exec { 'Register some failure':
command => '/var/tmp/register failure for /var/tmp/test',
}
?

You can try this :
exec { 'Notify a failure' :
command => "/var/tmp/register failure for /var/tmp/test",
path => "/bin:",
subscribe => File["/var/tmp/test"],
}

Related

Bad GET URL when using the Logstash http_poller input plugin

Trying to pull data from a public API using the Logstash http_poller input plugin:
input {
http_poller {
urls => {
method => "GET"
url => "https://api.example.com/v1/service/"
}
request_timeout => 60
schedule => { cron => "0 * * * *"}
codec => "json"
metadata_target => "http_poller_metadata"
}
}
filter {
}
output {
elasticsearch {
hosts => ["localhost:9200"]
}
}
Keep on getting a bad get URL error:
[ERROR][logstash.pipeline] Pipeline aborted due to error {:pipeline_id=>"main", :exception=>#<LogStash::ConfigurationError: Invalid URL GET>...]
Any idea what's causing this? The URL for the API is correct...
Turns out it was the method => "GET" line. Removing it worked like a charm.

Discord.js-commando: Stopping all commands if not in a specific channel

For testing I am trying to stop all commands, unless in a certain channel. I know how to do this for each command specifically, but I am trying to catch it inside of the main bot file, and return a message. I have tried two ways so far:
bot.on('command', async m => { (Also tried 'commandmessage')
console.log('COMMAND');
if (m.channel != 'bot-testing') {
return m.channel.send('You can\'t use commands here!');
}
});
Which doesn't work at all. Then I tried this:
bot.on('message', async m => {
m.isDM = (m.guild ? false : true);
if (m.content[0] != bot.commandPrefix) {
return;
} else {
if (m.channel != 'bot-testing') {
m.channel.send('You can\'t use commands here!');
}
}
});
Which kind of works, but doesn't stop the command.
It looks like you were super close - you just need to look at m.channel.name in your second if-statement (using method #2):
bot.on('message', async m => {
// ...
if (m.content[0] != bot.commandPrefix) {
return;
} else {
// [NEW: add .name prop here]
if (m.channel.name != 'bot-testing') {
m.channel.send('You can\'t use commands here!');
}
}
});

Chaining execs to be triggered by changes in a file

My requirement is this:
Look for changes in the file /tmp/file
If there is a change, execute these in the following order:
run command3
run command2
run command1
If there is NO change in the file /tmp/file, do nothing.
My code is like this:
exec { 'exec3':
command => 'command3',
require => File['file'],
}
exec { 'exec2':
command => 'command2',
require => Exec['exec3'],
}
exec { 'exec1':
command => 'command1',
require => Exec['exec2'],
subscribe => File['file'],
refreshonly => true,
}
But, whether there is a change to /tmp/file or not, command3 and command2 always runs. How do I prevent it? I do not want "require" to be run in exec1 when there is no change to /tmp/file.
You need: firstly, for all of the execs to subscribe to the file resource; secondly, for each of those to also require their preceding exec resources; and thirdly, for each exec to be set to refreshonly.
Here is some code that does that:
file { 'file':
ensure => file,
path => '/tmp/file',
content => "some content\n",
}
exec { 'exec1':
command => 'command1',
subscribe => File['file'],
refreshonly => true,
}
exec { 'exec2':
command => 'command2',
subscribe => File['file'],
require => Exec['exec1'],
refreshonly => true,
}
exec { 'exec3':
command => 'command3',
subscribe => File['file'],
require => Exec['exec2'],
refreshonly => true,
}
How this works:
Using exec's refreshonly mechanism, exec1 is triggered only on refresh events, and a refresh event is sent if and only if there is a change in file1's content.
All of the exec events need to be similarly triggered by the changes in the file's content, thus they all subscribe to the file.
But the execs need to be ordered in a specific way, and thus exec2 requires exec1, and exec3 requires exec2.
See also reasons why refreshonly needs to be used carefully.

What is a sensible way to structure my control flow (promises and looping)?

I'm not sure of how to adequately achieve my desired control flow using promises/bluebird.
Essentially I have a database with X 'tasks' stored and each needs to be loaded and executed sequentially. I don't want to run more than one task concurrently and the entire code must continue executing indefinitely.
I have achieved this with the following code so far:
export default function syncLoop() {
getNextTaskRunner().then((taskRunner) => {
if (taskRunner) {
taskRunner.startTask()
.then(syncLoop)
.catch((error) => {
throw new Error(error);
});
} else {
syncLoop();
}
});
}
getNextTaskRunner() simply loads and resolves with the next task from the database (calc'd based on timestamps). Or it resolves with null (no task avail).
taskRunner.startTask() resolves with null when the full task has completed.
I've been advised that the way it is structured (recursive /w promises) could lead to stack issues after it has been running for some time.
What I've thought about doing is to restructure it to something like:
let running = false;
setInterval(() => {
if (!running) {
running = true;
getNextTaskRunner().then((taskRunner) => {
if (taskRunner) {
taskRunner.startTask()
.then(() => {
running = false;
})
.catch((error) => {
log.error(error);
});
} else {
running = false;
}
});
}
}, 5000);
Or as yet another possibility, using event emitters in some form?
task.on('complete', nextTask());
Thoughts and advice will be greatly appreciated!
What stack issues? The way you've written your code is perfectly fine as long as getNextTaskRunner is truly async (i.e. it gives control back to the main loop at some point, e.g. if it does async io). There is no recursion in your code in that case. Whoever told you that is mistaken.
Though you might want to add a setTimeout somewhere so you won't flood your db with requests. Plus it will help you if getNextTaskRunner will no longer be sync (due to for example in memory caching):
export default function syncLoop() {
setTimeout(() => {
getNextTaskRunner().then((taskRunner) => {
if (taskRunner) {
taskRunner.startTask()
.then(syncLoop)
.catch((error) => {
throw new Error(error);
});
} else {
syncLoop();
}
});
}, 2000);
}

How to chain classes with commands

I have the following class which installs mysql and sets up a user called user but when the create-database commands runs the user has not been created yet.
How do i chain the commands so that the user is created before create-database tries to use it?
class { '::mysql::server':
package_name => 'mariadb-server.x86_64',
root_password => 'root',
remove_default_accounts => true,
override_options => $override_options,
restart => true,
users => {
'user#%' => {
ensure => 'present',
max_connections_per_hour => '0',
max_queries_per_hour => '0',
max_updates_per_hour => '0',
max_user_connections => '0',
password_hash => '...',
}
},
grants => {
'user#%/*.*' => {
ensure => 'present',
options => ['GRANT'],
privileges => ['ALL'],
table => '*.*',
user => 'user#%',
},
}
}->
exec { 'create-database':
creates => '/opt/dbinstalled',
command => '/usr/bin/mysql -u user -puser < /create-db.sql'
}
I am using the puppetlabs-mysql package to install mysql.
You should take a look at the documentation for the require, before, subscribe, notify metaparameters. They are used to describe resource ordering (before, notify), or resource ordering and failure if the dependency fails (require, subscribe). Note the subscribe, notify metaparameters are only available for some resource types (exec, service, etc.).
In this instance, you would do the following to chain a class:
exec { 'create-database':
creates => '/opt/dbinstalled',
command => '/usr/bin/mysql -u user -puser < /create-db.sql',
require => Class[::mysql::server],
}
But you really only need the dependency on the user resource:
exec { 'create-database':
creates => '/opt/dbinstalled',
command => '/usr/bin/mysql -u user -puser < /create-db.sql',
require => User[username or array of users],
}
Also you probably only want to create the database once, so we can give it a subscribe/refreshonly for idempotence:
exec { 'create-database':
creates => '/opt/dbinstalled',
command => '/usr/bin/mysql -u user -puser < /create-db.sql',
subscribe => User[username or array of users],
refreshonly => true,
}
Note that if you change the user resource that the create-database is subscribed to this will rerun the exec resource, so look into the unless, onlyif parameters for exec as other methods to establish idempotence.

Resources