In Puppet, can I realize a defined type for each element in an array? - arrays

After removing my variable names and everything extraneous for readability, my code comes down to this. I already set up a custom fact that returns an array of users that I need to set up some configuration files for. I'm trying to use a defined resource type and realize it with an array argument to do the configs for each user because Puppet lacks a basic for loop, so the code I have simplifies to this:
define modulename::pushconfigs{
user {"$name":
ensure => present
parameter => value
parameter => value
parameter => value
}
}
modulename::setconfigs{$::userlist: }
# $::userlist is an array of users, in the form [user1 user2 user3...]
for a couple parameters. However, when I try to run it, it says couldn't[do configs]for user user1 user2 user3. In other words, it's realizing the defined type only once, and it's trying to do so for a user whose name is the concatenated array.
How can I instead realize the defined type for each one in the array?

This should work...
define createuser{
user { $name :
ensure => present,
group => "gp",
home => "/home/$name",
shell => "/bin/bash",
}
}
$allusers = [ "user1", "user2", "user3", "user4" ]
createuser{$allusers:}

$::userlist is a string.
Its a fact, and facts are strings.
You need to turn it into an array before you can iterate over it.
If $::userlist = "user1,user2,user3"
$a_userlist=split($::userlist,',')
modulename::setconfigs{$a_userlist: }

Related

Extracting an array of values from an array of hashes in Puppet

I have the following array of hashes in hiera:
corporate_roles:
- name: 'user.1'
system_administrator: true
global_administrator: false
password: TestPassword1234
- name: 'user.2'
system_administrator: true
global_administrator: true
password: TestPassword1234
I need to extract a list of users with a give role (eg global_administrator) to be assigned later on.
I managed to use the map function to extract the data I need:
$corporate_roles = lookup('corporate_roles')
$global_admins = $corporate_roles.map | $hash | { if ($hash['global']){$hash['name']}}
notify { "global admins are: ${global_admins}":
}
However this results in undef values seemingly making their way into the array for the users that don't match the criteria:
Notice: /Stage[main]/salesraft_test/Notify[global admins are: [, user.2]]/message: defined 'message' as 'global admins are: [, user.2]'
Notice: Applied catalog in 0.04 seconds
I can get around this by using the filter function as such:
$test = $global_admins.filter | $users | {$users =~ NotUndef}
Which results in clean output:
Notice: /Stage[main]/salesraft_test/Notify[global admins are: [user.2]]/message: defined 'message' as 'global admins are: [user.2]'
Notice: Applied catalog in 0.03 seconds
But I suspect there must be a better way of doing this and I am either missing some logic in my map or I am likely using the wrong function altogether for this.
I would like to know if there is a better way to achieve what I am trying to do?
But I suspect there must be a better way of doing this and I am either
missing some logic in my map or I am likely using the wrong function
altogether for this.
map() emits exactly one output item for each input item, so if your objective is to apply a single function to obtain your wanted output from your (lengthier) input, then indeed, map will not achieve that.
I would like to know if there is a better way to achieve what I am trying to do?
Personally, I would do the job by filtering out the hashes you want from your input and then mapping those to the wanted output form (as opposed to mapping and then filtering the result):
$global_admins = $corporate_roles.filter |$hash| {
$hash['global_administrator']
}.map |$hash| { $hash['name'] }
I like that because it's nice and clear, but if you want to do it with one function call instead of two then you're probably looking for reduce:
$global_admins = $corporate_roles.reduce([]) |$admins, $hash| {
$hash['global_admin'] ? {
true => $admins << $hash['name'],
default => $admins
}
}

angular extract field of an array of object

I don't understand something and need explanations please !
I have a datatable and selection of lines generate in my .ts an array of Operation object. here is my object class :
export class Operation {
id: number;
name: string;
}
this is the declaration of array :
selectedOperations: Operation[];
when I log in console before extraction of ids, I have this :
this.selectedOperations = {"selected":[{"id":1,"name":"My name 1"},{"id":3,"name":"My name 3"}]}
and when I want to extract ids with this :
let ids = this.selectedOperations.map(o => o.id);
I have an exception =>
this.selectedOperations.map is not a function
It's not the first time I have this problem and I'd like to understand why. I search some reasons and found differences between Array and object[] ? I think it's not really an array because there is the {"selected": before the array...
Can someone tell me the thing and help me for extract ids ?
thanks a lot !
{"selected":[{"id":1,"name":"My name 1"},{"id":3,"name":"My name 3"}]} => this is of type object, whereas your array declaration looks like this selectedOperations: Operation[];
You either directly assign the array to your variable:
this.selectedOperations = [{"id":1,"name":"My name 1"},{"id":3,"name":"My name 3"}];
Or you can change your variable type to any or object:
selectedOperations: any;
this.selectedOperations = {"selected":[{"id":1,"name":"My name 1"},{"id":3,"name":"My name 3"}]}
const ids = this.selectedOperations.selected.map(o => o.id);
this.selectedOperations.map is not a function error is caused by the initialization, map function is reserved for arrays, therefore it throws an error when you try to use it on an object type variable.
I would recommend the first approach by the way, declaring a variable as any or object is contradicting with the purpose of Typescript.
You need to make some improvements to the code. In order to get the ids, you need to add selected to this.selectedOperations. See below.
let ids = this.selectedOperations.selected.map(o => o.id);

Create database seeder with same random value in a table row with Laravel database seeder

I am trying to create a table and populate the table with the following fields with the help of database seeder:
option a
option b
option c
option d
correct option
First four fields will be assigned random word, and the last field 'correct option' will contain any one of the first four.
I could not find any solution to do it with Laravel database seeder. Can anyone help?
Something like this?
use faker random element function in your factory or seeder.
$optionA = $faker->word;
$optionB = $faker->word;
$optionC = $faker->word;
$optionD = $faker->word;
return [
'option_a' => $optionA,
'option_b' => $optionB,
'option_c' => $optionC,
'option_d' => $optionD,
'correct_option' => $faker->randomElement([$optionA,$optionB,$optionC,$optionD]),
];
Create a factory and use Faker to generate the random words you're after
This sounds like an ideal use case for JSON columns (both for questions and answers). For instance, you might decide to have multiple valid answers to a single multiple choice question.
In your migration:
// create_questions_table.php
...
$table->json('choices')->default(new Expression('(JSON_ARRAY())'));
$table->json('answer')->default(new Expression('(JSON_ARRAY())'));
From https://laravel.com/docs/7.x/migrations#column-modifiers:
Using an Expression instance will prevent wrapping the value in quotes and allow you to use database specific functions. One situation where this is particularly useful is when you need to assign default values to JSON columns.
Then create a factory:
// QuestionFactory.php
$factory->define(Location::class, function (Faker $faker) {
$choices = $faker->words(4);
$answer = [ $choices[rand(1,4)] ];
return [
'choices' => $choices,
'answer' => $answer,
];
});
Using the Faker library included in Laravel, we can pick 4 words and randomly assign one of them to be the answer.

Can I check if a value is only pushed if a certain field value is not filled already?

I am trying to make a Meteor app to let users push a value to the database. It works ok, but there a small issue. As soon a certain user has pushed his information, i don't want to let the same user create another entry. Or this must be blocked, or the value the user is pushing must be overwritten for the value he is posting the second time. Now I get multiple entry's of the same user.
Here is my code. Hope you can help me here. Thanks in advance.
Estimations.update(userstory._id, {
$addToSet: {
estimations: [
{name: Meteor.user().username, estimation: this.value}
]
}
});
From the mongo docs
The $addToSet operator adds a value to an array unless the value is
already present, in which case $addToSet does nothing to that array.
Since your array elements are objects the value is the entire object, not just the username key. This means a single user can create multiple name, estimation pairs as long as the estimation value is different.
What you can do is remove any value for the user first, then reinsert:
var username = Meteor.user().username;
Estimations.update({ userstory._id },
{ $pull: { estimations: { name: username }}}); // if it doesn't exist this will no-op
Estimations.update({userstory._id },
{ $push: { estimations: { name: username, estimation: this.value }}});
By way of commentary, you've got a collection called Estimations that contains an array called estimations that contains objects with keys estimation. This might confuse future developers on the project ;) Also if your Estimations collection is 1:1 with UserStorys then perhaps the array could just be a key inside the UserStory document?

Pass variable from one WordPress hook to another

I have functions for two WordPress hooks: admin_menu and save_post
First I declare an associative array, which is called as global in both functions.
In the admin_menu function, I'm adding an additional key & value to the end of the array and I want the updated array to be available to the save_post function.
$my_array = array(
"key1" => "value1",
"key2" => "value2"
);
my_admin_function() {
global $my_array;
$my_array["key3"] => "value3";
}
my_save_function() {
global $my_array;
}
add_action('admin_menu', 'my_admin_function');
add_action('save_post', 'my_save_function');
In the above example, $my_array in my_save_function still only has 2 key/value pairs.
I can't figure out how to get my third key into my_save_function so it will get saved!
(Note: In my full code I'm using my_admin_function to add a meta box which cycles through an array of form fields, and then adds another field to the array. I'm then trying to save all of the fields in `my_save_function'.)
Well, you cannot do this because save_post action occurs before admin_menu action.
You should use another hook, e.g. init.

Resources