Puppet: load file content to variable (specifically hash variable) - puppet

I need to load the contents of some static files into some hash variables in Puppet in order to put them into a template. My folder layout is as follows:
./manifests/site.pp
./templates/script.sh.epp
./files/server1_part1.txt
/server1_part2.txt
/server2_part1.txt
/server2_part2.txt
What I want to do now is to load the contents of the ./files/${hostname}${part}.txt into the variables in a puppet hash in order to put them into the template. I know I could declare them in the site.pp but there are 10 machines all with different lines resulting in a manifest that would be unreadable.
Hash would look like this right now:
$script_config_hashes = {
part1 => "${source_path}/${hostname}_part1.txt",
part2 => "${source_path}/${hostname}_part2.txt",
part3 => "${source_path}/${hostname}_part3.txt",
}
Any idea on how to achieve this? Reading the documentation didn't answer my question (or I overlooked the obvious). Puppet Master is Version 6.X

You can load the contents of a file residing on the compile server via the Puppet file() function.
However, based on the appearance of manifests/site.pp, I get the idea that you have in mind to put this in the root of your environment. Don't. Instead, create a module, and put the files, the template, and the manifest that consumes them into that module. Aside from that being a widely accepted best practice, it will have the advantage of mooting the problem of constructing absolute paths to the wanted files.
With everything moved to module mymodule, the hash definition would look like this:
$script_config_hashes = {
part1 => file("mymodule/${hostname}_part1.txt"),
part2 => file("mymodule/${hostname}_part2.txt"),
part3 => file("mymodule/${hostname}_part3.txt"),
}
Note in particular that no absolute path is required, and that the "files/" part of the paths is implicit.

Related

How can I copy an existing overthere.SshHost file in XL Deploy UI using Puppet?

The Infra team in my company has provided us with sample overthere.SshHost under 'Infrastructure' in XL-Deploy UI that has a predefined private key file and passphrase which is not shared with us.
We are asked to duplicate this file manually in the UI, rename it and create infra entries for our application.
How can I achieve this with puppet?
Lets say the sample file is placed under: Infrastructure/Project1/COMMONS/Template_SshHost
and I need to create an overthere.SshHost under Infrastructure/Project1/UAT/Uat_SshHost and Infrastructure/Project1/PREPROD/Preprod_SshHost by copying the sample file.
Thanks in advance!
You can sync a target file with another file accessible via the local file system by using a File resource whose source attribute specifies the path to the original. You can produce a modified copy in a variety of ways, such as by applying one or more File_line resources (from stdlib) or by applying an appropriate script via an Exec resource.
But if you go that route then you have to either
accept that the target file will be re-synced on every Puppet run, OR
set the File resource's replace attribute to false, in which case changes to the original file will not be propagated into the customized copy.
The latter is probably the more acceptable choice for most people. Its file-copying part might look something like this:
$project_dir = '/path/to/Infrastructure/Project1'
file { "${project_dir}/UAT/Uat_SshHost/overthere.SshHost":
ensure => 'file',
source => "${project_dir}/COMMONS/Template_SshHost/overthere.SshHost",
replace => false,
}
But you might want to consider instead writing a custom type and provider for the target file. That would allow you to incorporate changes from the original template without re-syncing the file on every run, and it would give you a lot more flexibility with respect to the customizations you need to apply. It would also present a simpler interface for you to use in your manifests, which could make managing these easier. But, of course, that's offset by the cost is that writing and maintaining a custom type and provider. Only you can determine whether that would be a worthwhile trade-off.

Nodejs Pkg - how to use an external Config file?

I am having issues attempting to properly use pkg (nodejs module) properly.
I am doing a stand alone file manager (well, it would swap video/audio files to & from preselected directories, intended to allow it without any internet connection it self to remove & add files to a syncing folder like onedrive/dropbox/googledrive/etc. using a text file.)
The issue I am having, is I am at a loss of after I package it into a binary.. I do not understand how to allow/force it to create/read the text file outside compiled binary.
-- I would love for it to be within the same folder as the executable.
I am attempting to find a way to store data without having to share the sourcecode, or require node be installed on other machines.
-- I intend to have a minimal permissions as possible, and outside reading/writing the config & 'database' [which is simply a text file with what files are in the local storage, and what files are & are not in the remote storage]
What am I missing about pkg, & if it can store data internally some how... how do I get it to read an external file?
-- Though I would greatly prefer to have the txt files outside the binary & in plain text easy to read.
As a side question, I am not understanding how to pass an argument through & use it inside the program after it's compiled. [Hell, I'm having a heck of a time, properly understanding the readme for the pkg module]
Use fs features to load config object as in this three-lines of code
filename="./config.json";
let rawdata = fs.readFileSync(filename);
let config = JSON.parse(rawdata);
config.json must be in same direcory of pkg executable
If you need to change path of config.json, you will able to specify full-path of this file using command line arguments.
These can be read at runtime using process.argv variable as explained here

Terraform conditional source in MODULE

I am trying to set a module's source (this IS NOT a resource) based on a conditional trigger but it looks like the module is getting fired before the logic is applied:
module "my_module" {
source = "${var.my_field == "" ? var.standard_repo : var.custom_repo}"
stuff...
more stuff...
}
I have created the standard_repo and custom_repo vars as well and defined with URLs for respective repos (using git:: -- this all works w/o conditional)
All this being said, anyone know of a way to implement this conditional aspect? (again, this is a module and not a resource)
I tried using duplicate modules and calling based off the var value but this, too, does not work (condition is never met, even when it is):
repo = ["${var.my_field == "na" ? module.my_module_old : module.my_module_new}"]
One way to achieve this is described in this post
Basically, a common pattern is to have several folders for different environments such as dev/tst/prd. These environments often reuse large parts of the codebase. Some may be abstracted as modules, but there is still often a large common file which is either copy-pasted or symlinked.
The post offers a way that doesn't conditionally disable based on variables but it probably solves your issue of enabling a module based on different enviornments. It makes use of the override feature of terraform and adds a infra_override.tf file. Here, it defines a different source for the module which points to an empty directory. Voila, a disabled module.
Variables are not allowed to be used in the module source parameter. There also does not seem to be a plan for this to change. https://github.com/hashicorp/terraform/issues/1439 . Creating a wrapper script , or using something like mustache http://mustache.github.io/ seems to be the best way to solve the problem.

In Puppet using Hiera, where do I put the files I want to have installed on nodes?

I know puppet modules always have a files directory and I know where it's supposed to be and I have used the source => syntax effectively from my own, handwritten modules but now I need to learn how to deploy files using Hiera.
I'm starting with the saz-sudo module and I've read the docs but I can't see anything about where to put the sudoers file; the one I want to distribute.
I'm not sure whether I need to set up a site-wide files dir in /etc/puppetlabs/puppet and then make subdirs in there for every module or what. And does Hiera know to look in /etc/puppetlabs/puppet/files/sudo if I say, source => "puppet:///files/etc/sudoers" ? Do I need to add a pathname in /etc/hiera.yaml? Add a line - files ?
Thanks for any clues.
My cursory view of the puppet module, given their example of using hiera:
sudo::configs:
'web':
'source' : 'puppet:///files/etc/sudoers.d/web'
'admins':
'content' : "%admins ALL=(ALL) NOPASSWD: ALL"
'priority' : 10
'joe':
'priority' : 60
'source' : 'puppet:///files/etc/sudoers.d/users/joe'
Suggest it assumes you have a "files" puppet module. So under you puppet modules section:
mkdir -p files/files/etc/sudoers.d/
Drop your files in there.
Explanation:
The url 'puppet:///files/etc/sudoers.d/users/joe' is broken down thus:
puppet: protocol
///: Three slashes indicate the source of the file is in a module.
files: name of the module
etc/sudoers.d/users/joe: full path to the file within the module's "files" directory.
You don't.
The idea of a module (Hiera backed or not) is to lift the need to manage the whole sudoers file from you. Instead, you can manage each single entry in the sudoers file.
I recommend reviewing the documentation carefully. You should definitely not have a file { "/etc/sudoers": } resource in your manifest.
Hiera doesn't have to do anything with Files.
Hiera is like a Variables Database, and servers you based on the hierarchy you have.
the files inside puppet, are usually accessed in methods like source => but also these files are using some basic structure.
In most cases when you call an file or template.
A template can serve your needs to automatically build an sudoers based on that.
There are also modules that supports modifying sudoers too.
It is up to you what to do.
In this case, saz stores the location of the file in hiera, but the real location can be a file inside your puppet (like a module file or something similar).
Which is completely unrelated.
Read about puppet file server
If you have questions, just ask.
V

ClassLoader.getSystemResource(...).getPath() seems to return wrong path

I'm trying to wrap code that requires two *.db4o data files for easy use. I've added the data files to my eclipse .classpath by placing the files in ${project_dir}/res/ and adding the line:
<classpathentry kind="src" path="res"/>
to my .classpath.
I then defined a default constructor to my wrapper class that takes no arguments but goes and finds the paths to the *.db4o files (the paths are required by the compiled code I'm using to set things up). My approach for getting the paths is:
String datapath = ClassLoader.getSystemResource("resource_name").getPath();
This works great when I debug/run my code in eclipse. However when I export it as a jar, I can see that the *.db4o files are in the jar, as well as my compiled code, but the path returned to "datapath" is of the form:
datapath = ${pwd}/file:${absolute_path_to_jar}!/{resource_name}
Is there something about the resource being inside of the jar that prevents an absolute path from working? Also, why is the behavior different simply because the code and resources live in a jar file? One last note is that while my application is intended for wider use (from PIG, python, etc. code) I'm testing it from Matlab which is where I'm getting the odd value assigned to "datapath".
Thanks in advance for any responses.
getSystemResource() returns URL to resource. If your resource is zipped in a jar file then the URL will point into it (with the "!" notation). getPath() returns the "path" part of the URL, not always an actual file path. URL can be one of many things, not just a file.

Resources