I set up a Virtual box with RHEL 5.11 (for now) and installed chef-client v12.5.1, and logged in as root. I setup my knife.rb file and am able to do knife commands, like knife node list for example. I set up a user “Jenkins” and associated pem file for communication with the Chef server, which is v12.0.3
IIRC a regular user cannot create clients, you have to be an admin. This may have changed in a more recent version of Chef Server to accommodate the “validatorless” bootstrapping feature but I am not sure.
I have a java cookbook that installs Java, among other things, in a RHEL6 distro. How can I set JAVA_HOME so it persists in the environment, that is, when the cookbook finishes, I can go to my command line I can type echo $JAVA_HOME and see the setting. I do
bash ‘Set JAVA_HOME’ do
code <<-EOF
export JAVA_HOME=/etc/alternatives/java
EOF
end
But I don’t get anything when I do echo $JAVA_HOME from command line
In *nix OSes, environment variables are inherited from the parent process when a new process is created, and from there processes may set environment variables for themselves and any processes they create in the future. In the case of a shell, this is handled by various profile and rc scripts that provide system-wide and per-user customization. A good thing to read is the "invocation" section of the bash manual page: http://linux.die.net/man/1/bash In any case, the recommended way to make modifications to these files can vary by distro and I don't remember off-hand how you're supposed to do it for EL, but you should be able to google some combo of these terms and get an answer.
So, what your code is doing is, Chef Client creates a bash process; that bash process sets an environment variable for itself (which can only affect processes that it creates); then it exits, having changed nothing that would affect the environment variables of existing or future processes.
How about adding the environment variable to the user’s profile file (for example .bash_profile if user’s default shell is bash) via chef?
ruby_block "Update user's profile file" do
block do
file = Chef::Util::FileEdit.new("/home/<user>/.profile")
file.insert_line_if_no_match("export JAVA_HOME=/usr/bin/java", "export JAVA_HOME=/usr/bin/java")
file.write_file
end
end
Libraries are evaluated as regular ruby code, whereas Attributes files and Recipes are evaluated inside a DSL.
Your suggested solution for loading the node object from the server won't work, because it creates a second copy of the node object, which won't affect the primary copy.
What you need to do is create a module and define a method on it, then use that elsewhere. The simplest way is to use module functions which take a node as an argument. That looks like:
module MyHelperFunctions
def self.compute_a_value(node)
node[:my_cookbook][:attr1]
end
end
You would access that with code like MyHelperFucntions.compute_a_value(node)
The other way to go is to mix your module in to the recipe DSL. The tricky part about that is that when you create a resource, the part between the do and end is actually a DSL for just that resource, so you have to mix your module into both the recipe and resource to make it work everywhere.
To illustrate:
# in recipes/whatever.rb
# this area here is the **recipe** DSL
file "/tmp/foo.rb" do
# this area here is a DSL for just the file resource
mode "0755"
# etc.
end
# now you're back in the recipe DSL
So if you want to define a method that can implicitly use the node object, you have to do something like this:
module MyHelpers
def computed_value
node[:my_cookbook][:attr1]
end
end
Chef::Recipe.send(:include, MyHelpers)
Chef::Resource.send(:include, MyHelpers)