I have a module which reportedly required puppetlabs-stdlib.
[vagrant#learn puppet]$ sudo /opt/puppetlabs/bin/puppet module list --tree --modulepath=/vagrant/puppet -v
Warning: Missing dependency 'puppetlabs-stdlib':
'elk' (v0.1.0) requires 'puppetlabs-stdlib' (>= 1.0.0)
/vagrant/puppet
└─┬ elk (v0.1.0)
└── UNMET DEPENDENCY puppetlabs-stdlib (>= 1.0.0)
I installed the module as follows:
[vagrant#learn puppet]$ sudo /opt/puppetlabs/bin/puppet module install puppetlabs-stdlib
Notice: Preparing to install into /etc/puppetlabs/code/environments/production/modules ...
Notice: Downloading from https://forgeapi.puppet.com ...
Notice: Installing -- do not interrupt ...
/etc/puppetlabs/code/environments/production/modules
└── puppetlabs-stdlib (v6.1.0)
However, the missing dependency is not resolved still. How can I make Puppet see the lib that I installed?
The command
sudo /opt/puppetlabs/bin/puppet module list --tree --modulepath=/vagrant/puppet -v
Reports that the elk module's dependency on puppetlabs-stdlib is unmet, whereas you show that module to be installed in /etc/puppetlabs/code/environments/production/modules. These facts are consistent.
The --modulepath argument to puppet module list does not do what you seem to expect. This might be more clear if you took into account Puppet's definition of the term:
The master service and the puppet apply command load most of their
content from modules found in one or more directories. The list of
directories where Puppet looks for modules is called the modulepath.
The modulepath is set by the current node's environment.
The modulepath is an ordered list of directories, with earlier
directories having priority over later ones. Use the system path
separator character to separate the directories in the modulepath
list. On *nix systems, use a colon (:); on Windows use a semi-colon
(;).
The --modulepath option to your puppet module list command expresses a complete modulepath, and accordingly, in your command it tells Puppet to consider only modules in /vagrant/puppet. With respect to that modulepath, the stdlib dependency is indeed unmet.
This alternative should show the dependency satisfied:
sudo /opt/puppetlabs/bin/puppet module list --tree \
--modulepath=/etc/puppetlabs/code/environments/production/modules:/vagrant/puppet -v
What significance either result has at Puppet runtime depends on the modulepath Puppet is using for catalog building. If you leave off the --modulepath option altogether then you will get results relevant to Puppet's current configuration and default environment, which might or might not be more relevant to your actual usage scenario.
You are not referencing the same modulepath.
In the first instance, you are listing modules from /vagrant/puppet as per your --modulepath statement.
When you install, you did not specify a modulepath, so as per std out of the install:
Notice: Preparing to install into /etc/puppetlabs/code/environments/production/modules
So you have to either point the stdlib install to the same path: puppet module --modulepath=/vagrant/puppet install puppetlabs-stdlib, or update the modulepath of the client to run off the default, /etc/puppetlabs/code/environments/production/modules
Related
I'm attempting to create a Chef cookbook that, for now, is mostly just a wrapper cookbook for another cookbook (the audit cookbook). I'm still learning Chef, but from what I can gather from the About Recipes documentation and the Resources Reference documentation, Chef recipes should execute in the order that they're defined (via Ruby code and/or Chef resources).
In the About Recipes documentation, it mentions that
When a recipe is included, the resources found in that recipe will be
inserted (in the same exact order) at the point where the
include_recipe keyword is located.
In the Resources Reference documentation, they have an apt_update resource that presumably executes before the include_recipe method due to the fact that it's defined earlier in the recipe.
My wrapper cookbook has a single recipe, default.rb, which is literally these two lines:
package 'ruby-dev'
include_recipe 'audit'
However, during a chef-client or chef-solo run I see that the audit::inspec recipe runs before the security::default recipe which causes things to break because InSpec has some other dependencies that need to be installed beforehand. Before I used the package resource I was using the execute resource to explicitly run apt-get install ruby-dev or yum install ruby-dev depending on the platform using a case statement, but same problem (all that code was skipped and the include_recipe method called first).
In case it's useful, I'm using Chef 12 which I realize is EOL but I have other dependencies that require me to stick with this version of Chef for now.
I may very well just be misunderstanding how Chef converges work and the order in which execution occurs, but it's causing me a lot of grief so I'd really appreciate some pointers! Does include_recipe always occur before other code within your recipe? Is there any way around this? Am I missing something?
-- EDIT --
I was able to get the desired functionality (install other packages and gems before an include_recipe call triggered installation of a dependency gem) using the following code in my cookbook recipe:
package 'build-essential' do
action :nothing
end.run_action(:install)
chef_gem 'train' do
version "1.4.4"
action :install
end
chef_gem 'signet' do
version "0.11.0"
action :install
end
include_recipe 'audit'
Note that I ended up installing the build-essential package rather than the ruby-dev package from my original code snippet, and also installed two gems for Chef client to use. This all gets installed in the order I expected during the compile phase of the Chef run.
Sources:
https://docs.chef.io/resource_reference.html#run-in-compile-phase
https://docs.chef.io/resource_chef_gem.html
if you would examine the audit::inspec rescipe, you will find that it uses a compile time installation of the inspec rubygem (see the last line)
inspec_gem 'inspec' do
version node['audit']['inspec_version']
source node['audit']['inspec_gem_source']
action :nothing
end.run_action(:install)
from chef documentation:
run_action
Use .run_action(:some_action) at the end of a resource block to run the specified action during the compile phase.
I am experimenting with Puppet using Vagrant. I'm new to Puppet.
I'm installing modules in my Puppet manifest using the approach suggested at: Can I install puppet modules through puppet manifest?
My default.pp contains something like:
$dsesterojava = 'dsestero-java'
exec { 'dsestero-java':
command => "puppet module install ${dsesterojava}",
unless => "puppet module list | grep ${dsesterojava}",
path => ['/usr/bin', '/bin']
}
include java::java_7
I'm trying to import a module and then immediately use the classes defined in it.
Currently, I get:
Error: Could not find class java::java_7
If I comment out the include line and re-run it. The module installs. If I then removed the comment and run the provisioning again then it works.
There is some kind of "chicken and egg" situation here. Can I use a module in the same Puppet manifest that installs it?
How should I solve it?
No, you cannot do this. When your catalog is compiled, Puppet will search in the appropriate directories for all of the required code and data. Since the java module does not exist until catalog application, the compilation of a catalog (occurs prior to application) depending upon it will fail. You are absolutely dealing with a "chicken and egg" situation here. I highly recommend against using Puppet code to install Puppet code.
Alternatively, the recommended approach to install and manage your Puppet modules is to use one of these solutions:
librarian-puppet: http://librarian-puppet.com/
r10k: https://github.com/puppetlabs/r10k
code-manager (PE only): https://puppet.com/docs/pe/2017.3/code_management/code_mgr.html
These will also solve the problem for you within the Vagrant if you are using the agent provisioner and subscribing the Vagrant instance to a Puppet Master.
If you are using the apply provisioner inside of Vagrant, then you will need to go a different route. The simplest solution is to use the shell provisioner to install Puppet modules via module install after the Puppet installation (unless you are using a Vagrant box with Puppet baked in, in which case you are probably not installing Puppet on it). Alternatively, you could share a directory with the host where your modules are installed, or install the librarian-puppet or r10k gems onto the Vagrant box and then use them to install into the appropriate path. I can go into more detail on these upon request.
eg.
I am writing a wrapper cookbook (my_cookbook) for the same purpose I am using the community cookbook (community_cookbook). I face an issue regarding the dependency list present in community_cookbook.
The metadata.rb file in community_cookbook has the following dependency list.
...
depends mysql
depends postfix
...
So, by default the run-list has the latest version (say 8.3.0) of mysql cookbook.
My question is what changes should I be making in order to get previous version of mysql (say 5.3.6).
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
What steps did I take to solve this problem ?
Ans:
I wrote the following in metadata.rb of my_cookbook.
...
depends 'mysql', '~> 5.6.3'
depends 'community_cookbook', '~> 1.1.0'
...
And I got this following message on the console
>>>>>> Failed to complete #converge action: [Unable to satisfy the following requirements:
- `mysql (= 8.3.0)` required by `user-specified dependency`
- `mysql (~> 5.6.3)` required by `my_cookbook-0.1.0`
- `mysql (>= 0.0.0)` required by `community_cookbook-1.1.0`
- `mysql (>= 6.0.0)` required by `php-3.0.0` # This is because the community_cookbook also has php as it's dependency list.
You might have changed the Berksfile.lock manually and it is causing the above issue.
can you try to deleting Berksfile.lock(take backup) and do berks install and then upload?
it should install all the necessary version of mysql cookbook
and then all the cookbook can have the mysql version they require
It sounds like you have something funky in your Berkfile or Policyfile. Check for unintended version pins there and possibly run berks update to force a re-solve. The user-specified-dependency means that constraint is coming from outside the cookbook system, usually via a manual cookbook 'mysql', '8.3.0' in a Berksfile but there are other ways like environment constraints or run list version hacks.
I have a hard time dealing with the puppet modules of my Vagrant. This is mainly due to the fact that neither r10k nor librarian-puppet handle transitive dependencies. That is, if I have a Puppetfile that points to a puppet module which itself contains a Puppetfile, then this last Puppetfile is ignored.
You can try this tool : https://github.com/backuity/puppet-module-installer
It is an asset to your private puppet infrastructure :)
I'm working with someone else's chef recipe and it consists of these references to the process of installing 1.9.3p0 on my server:
package 'ruby1.9.3'
package 'ruby1.9.1-dev'
# set ruby 1.9 to be default
execute 'update-alternatives --set ruby /usr/bin/ruby1.9.1'
execute 'update-alternatives --set gem /usr/bin/gem1.9.1'
ohai "reload" do
action :reload
end
I'm new to chef so I'm not sure where these packages reside, but seeing no other reference them to them in the repo of recipes, I'm guessing it's referring to a central repo. In that case, how could I modify this recipe to get chef (solo) to prepare my servers with a different patch level?
The documentation may clear things up a little here:
package tells the chef-client to use one of sixteen different
providers during the chef-client run, where the provider that is used
by chef-client depends on the platform of the machine on which the
chef-client run is taking place
So on Debian-based systems like the one that recipe was written for, Chef will automatically resolve the package resource to an apt_package resource, which will call apt-get to install ruby1.9.3.
Now, given none of the mainstream Linux distros or FreeBSD package up multiple patchlevels of Ruby (and, in some cases, stated patchlevels are not what they seem), you probably don't want to use package to get Ruby. Most likely you'll end up wanting to build it from source using something like the bash resource.
package will still be useful for installing the Ruby prerequisites, which you can use from your vendor's package repository without issue.