Puppet: manage the recursiveness of owner/group/mode attributes separately - puppet

I need to write a Puppet script to manage the directory /foo/bar such that:
the file mode on /foo/bar is 777, but the permissions of everything within the directory are not managed by Puppet.
the owner/group on /foo/bar and everything within it is baz.
That is, the first requirement is non-recursive, but the second attribute is recursive.
Puppet provides a single recursive attribute, which affects the behavior of owner, group, and mode simultaneously. This means that I cannot specify the desired behavior using a single resource declaration.
I tried using two resource declarations, but then I get the error
Error: Duplicate declaration: File[/foo/bar] is already declared in file /my/puppet/file.pp at line XX; cannot redeclare

Yes, this will not work. Mind that Puppet is not a scripting engine, but a tool to model your desired state.
You will therefor have to decide how you want to manage your directory: As a single file system entry (recurse => false) or a whole tree (recurse => true). In the latter case, Puppet will always manage all properties for which you are passing values.
In your situation, you will likely have to fall back to the workaround of managing the permissions of the directory itself through a different resource, likely an exec resource that calls chmod, independently of the file resource. The latter must not pass a value for mode in this constellation, otherwise the two resources will always work against one another.
It's no ideal, but Puppet is not well equipped to deal with your specific requirements.

Related

How to set ownership on multiple directories in puppet?

I have a bunch of directories [ "mydir", "mydir1", "mydir2" , "mydir3" ]. This list will grow eventually.
How can i set the ownership of directories "mydir*" ?. Will the wildcard * can be used in puppet resource.I am aware of the looping through the array of directories and setting up the permission. Since this list is growing i want to use some wildcard like "mydir*".
The short answer is no, Puppet does not support wildcard resource names. There is a good explanation with workarounds at https://ask.puppet.com/question/15769/can-we-use-wild-cards-in-file-resource-path-and-source-parameters/.
The longer answer is no, Puppet does not support wildcard resource names, because the resources are typically enumerated on the Puppet server, which doesn't have access to the client filesystems and so can't run a wildcard to generate matches. As the Puppet answer above says, one option is to use an exec resource to set the ownership using a shell glob, something like
exec { 'Change owner and group to user.group on /bar/foo*':
path => '/bin',
command => 'chown user.group /bar/foo*',
}
Note that the use exec resources has problems of its own. In this particularly example, the resource is not idempotent, so will run every time Puppet agent runs, which is not generally acceptable.

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.

custom type/provider case insensitive title

Is there anyway to normalize the title value through a munge call or something similiar?
I have a custom type/provider that manages local group membership on Windows machines (we needed more granularity over group membership, than just inside the user/group types.
group_member{"Group => Member":
ensure=>present,
}
group_member{"Group => DOMAIN\Member":
ensure=>present,
}
resources{'group_member':
purge =>true,
}
In general, when everything is consistent everything works great. The issue comes in that windows/active directory are not case sensitive. Therefore, when self.instances gets called, It generates a resource Group_member["Users => DOMAIN\SomeGroup"], but in our puppet manifest, Users is hardcoded, DOMAIN comes from a fact, and SomeGroup comes from a hiera value.
We've been fighting with the case sensitivity of puppet for about 5 years on this, and most of our administrators have gotten used to ensuring case matches between domain and yaml configurations.
Now, we have a new problem... somehow DOMAIN is messing up. On a new testing domain, the NETBIOS name is lowercase. The fact we had returning DOMAIN still returns uppercase, but Windows ADSI is returning a lowercase form. This wouldn't be an issue if we wern't using resources{'group_member': purge=>true}, but now in this test environment the groups get added (through their respective .pp files) and removed (through resources{'group_member': purge=>true}}) every puppet run.
Ideally i'd like to just normalize everything to lowercase in self.instances and in all of our .pp files, but we have 400 puppet modules and we use group_member 120 times, managed by quite a few different teams. It would be significantly easier if I could just munge the title metaparameter.
Any suggestions?
So, the way i'm handling this is to rename the existing type/provider and wrapping it in a define type that downcase's the title.

Chef: use attributes created dynamically

I have 2 recipes that belongs to the same cookbook.
The first recipe uncompress the apache-tomcat-xxx.tar.gz file in /opt/tomcat/apache-tomcat-xxx
In that first recipe I do
tomcat_folder = ls /opt/tomcat
node.default['tomcat']['home'] = "/opt/tomcat/#{tomcat_folder}"
so this attribute is created during execution of that recipe.
My second recipe needs to use that attribute value in resource like:
template node.default['tomcat']['home'] ...
directory node.default['tomcat']['home'] ...
and
ruby_block
block do
node.default['tomcat']['home'] ....
But I receive errors due to that attribute doesn't exist when it executes.
In some other resources I could make it work using lazy{…} blocks, but in those resources I don't know how to make them work.
So my question is, how shall I do to set that attribute from recipe 1 so it is able to be used from recipe 2 when they are executed?
Here you also can use lazy, but with some workaround.
template 'tomcat_home' do
path lazy { node['tomcat']['home'] }
end
directory 'tomcat_home' do
path lazy { node['tomcat']['home'] }
end
path for directory and template is a name attribute, which means, if it is not set inside the block it is taken from the name of the resource. This is how you did it before. But if you need lazy evaluation, you can set any string as the name of the resource. Just make sure, you don't create same resources with same names, but different bodies, as they will overwrite each other.
Another thing you shouldn't to read an attribute from particular precedence level (default, normal, override). Just node['tomcat']['home'] is the way to go.

NFS CREATE File (overwrite) = zero size?

Im implementing NFS and almoste done but the RFC section 3.3.8 says this in its description:
mode
One of UNCHECKED, GUARDED, and EXCLUSIVE. UNCHECKED
means that the file should be created without checking
for the existence of a duplicate file in the same
directory. In this case, how.obj_attributes is a sattr3
describing the initial attributes for the file. GUARDED
specifies that the server should check for the presence
of a duplicate file before performing the create and
should fail the request with NFS3ERR_EXIST if a
duplicate file exists. If the file does not exist, the
request is performed as described for UNCHECKED.
EXCLUSIVE specifies that the server is to follow
exclusive creation semantics, using the verifier to
ensure exclusive creation of the target. No attributes
may be provided in this case, since the server may use
the target file metadata to store the createverf3
verifier.
so the question if UNCHECKED is the mode should i just set the length of the file to Zero or should i let the file be as it is? and if its a directory should i remove all the content?
I believe the idea of CREATE with UNCHECKED is to apply the semantics of good old Unix system call creat -- so, truncation of a file's existing contents (if any) is implied. However I cannot find this specified all that clearly in the docs (!).
Trying to CREATE an existing directory is an error in any case -- there's a separate MKDIR for that (in NFS 3, the same applies to special files, with MKNOD -- CREATE is now for regular, normal, plain good old files only!-)

Resources