I need some assistance defining variables in a chef recipe - ruby

Here is the LDAP command that I want to run, which works perfectly:
/opt/openldap/setup —cli —no-prompt —rootUserDN "cn=Directory Manager" — rootUserPasswpord secretpass —hostname localhost —ldapPort 389 —adminConnectorPort 4444 —baseDN "dc=example,dc=com" —addBaseEntry —doNotStart —acceptLicense'
Here is the content of my chef attribute file (server.rb)
default["openldap"]["server"]["ROOTDN"] = "cn=Directory Manager"
default["openldap"]["server"]["ROOTPASS"] = "secret pass"
default["openldap"]["server"]["LDAPPORT"] = "389"
default["openldap"]["server"]["ADMINPORT"] = "4444"
default["openldap"]["server"]["BASEDN"] = "dc=example,dc=com"
default["openldap"]["server"]["DJDEST"] = "/opt/openldap"
Here is the content of my chef recipe file (default.rb)
execute 'Ldap: Installing Openldap Instance' do
command node["openldap"]["server"]["DJDEST"]'/setup --cli --no-prompt--rootUserDN "["openldap"]["server"]["ROOTDN"] " --rootUserPassword ["openldap"] ["server"]["ROOTPASS"]--hostname ["openldap"]["server"]["ODJFQDN"] --ldapPort ["openldap"]["server"]["LDAPPORT"] --adminConnectorPort ["openldap"]["server"]["ADMINPORT"] --baseDN "["openldap"]["server"]["BASEDN"]" --addBaseEntry --doNotStart --acceptLicense'
action :run
end
I want to run the execute resource using variables instead of manually hardcoding the ldap script in the code block. Can anyone please advice me on what i am doing wrong?

Assuming that I understand your question right, you want to generate a string from few variables and strings. Then your question is similar to this one.
You could either combine the content of a variable a = "foo" and the string "bar" using:
a = "foo"
b = a + "bar"
Or you can use string interpolation (probably more common):
a = "foo"
b = "#{a}bar"
The result in both cases is "foobar".
Translated to your chef context, the resulting execute resource would be:
execute 'Ldap: Installing Openldap Instance' do
command "#{node['openldap']['server']['DJDEST']}/setup --cli --no-prompt--rootUserDN "#{node['openldap']['server']['ROOTDN']}" --rootUserPassword #{node['openldap']['server']['ROOTPASS']} --hostname #{node['openldap']['server']['ODJFQDN']} --ldapPort #{node['openldap']['server']['LDAPPORT']} --adminConnectorPort #{node['openldap']['server']['ADMINPORT']} --baseDN "#{node['openldap']['server']['BASEDN']}" --addBaseEntry --doNotStart --acceptLicense"
action :run
end
If it makes it easier for you, you can also extract this into a variable:
installLdapCommand = "#{node['openldap']['server']['DJDEST']}/setup --cli --no-prompt--rootUserDN #{node['openldap']['server']['ROOTDN']} --rootUserPassword #{node['openldap']['server']['ROOTPASS']} --hostname #{node['openldap']['server']['ODJFQDN']} --ldapPort #{node['openldap']['server']['LDAPPORT']} --adminConnectorPort #{node['openldap']['server']['ADMINPORT']} --baseDN "#{node['openldap']['server']['BASEDN']}" --addBaseEntry --doNotStart --acceptLicense"
execute 'Ldap: Installing Openldap Instance' do
command installLdapCommand
action :run
end

Instead of
'["openldap"]["server"]["ROOTDN"] --option'
try using ruby's string interpolation
"#{node['openldap']['server"]['ROOTDN']} --option"
Like so:
execute 'Ldap: Installing Openldap Instance' do
command "#{node['openldap']['server']['DJDEST']}/setup --cli --no-prompt--rootUserDN #{node['openldap']['server']['ROOTDN']} --rootUserPassword #{node['openldap']['server']['ROOTPASS']} --hostname #{node['openldap']['server']['ODJFQDN']} --ldapPort #{node['openldap']['server']['LDAPPORT']} --adminConnectorPort #{node['openldap']['server']['ADMINPORT']} --baseDN #{node['openldap']['server']['BASEDN']} --addBaseEntry --doNotStart --acceptLicense"
action :run
end

Related

To get IP addres of the specific host machine in rub

I want to find the IP address of other system. For example, I am executing my code from server wevrs1234 and I want the IP address of server apvrs1234 and store it in variable. Please help me to get this.
ip = IPSocket.getaddress(Socket.gethostname)
is the code I have so far.
AS per suggestion i have made this code but getting error. Please find my code
publish_vm = node['aem_dispatcher_cookbook']['publish'].to_s
nodes = search(:node, 'hostname:publish_vm')
node.default['aem_dispatcher_cookbook']['ip_address'] = 'nodes.first['ipaddress']'
template node['aem_dispatcher_cookbook']['owner']['home'] + '/conf.d/publish_farm.any' do
source 'publish_farm.any.erb'
owner node['aem_dispatcher_cookbook']['owner']['user']
group node['aem_dispatcher_cookbook']['owner']['group']
mode '0755'
variables(
publish_host: node['aem_dispatcher_cookbook']['publish'],
publish_port: node['aem_dispatcher_cookbook']['publish_port'],
ip_addr: node['aem_dispatcher_cookbook']['ip_address']
)
end
Error
[2020-05-20T06:09:52-05:00] DEBUG: Node wevrd64501.uhc.com loading cookbook aem_dispatcher_cookbook's attribute file /root/.chef/local-mode-cache/cache/cookbooks/aem_dispatcher_cookbook/attributes/default.rb
================================================================================
Recipe Compile Error in /root/.chef/local-mode-cache/cache/cookbooks/aem_dispatcher_cookbook/recipes/default.rb
================================================================================
SyntaxError
-----------
/root/.chef/local-mode-cache/cache/cookbooks/aem_dispatcher_cookbook/recipes/default.rb:333: syntax error, unexpected tIDENTIFIER, expecting keyword_end
...ess'] = 'nodes.first['ipaddress']'
... ^~~~~~~~~
System Info:
You tagged the question with [chef] and [chef-recipe], so I understand you are trying to get another machine's IP address inside recipe. If that another machine is also registered with Chef Server, the easiest would be search. You can search for any machine registered on the Chef Server by some attribute, in your case - hostname.
nodes = search(:node, 'hostname:<another_vm_hostname>')
p nodes.first['ipaddress']
Update:
You have an error in your 3rd line. Don't surround nodes.first['ipaddess'] with quotes.
node.default['aem_dispatcher_cookbook']['ip_address'] = nodes.first['ipaddress']
publish_vm = node['aem_dispatcher_cookbook']['publish'].to_s
ruby_block 'get_ip_from_publish' do
block do
Chef::Resource::RubyBlock.send(:include, Chef::Mixin::ShellOut)
command1 = "nslookup #{publish_vm} |grep '^Address' | awk '{print $2}'| tail -1"
command_out = shell_out(command1)
node.run_state['master_ip'] = command_out.stdout
end
action :run
end
This piece of code helped me to get ip address of desired host machine

How to use local variable of whitespace array in chef template resource

I am trying to use whitespace arrays in chef template, like below and when I run the chef-client to execute the recipe getting an error saying: option variables must be a kind of [Hash]! below is recipe file
abc = node['abc']
def1 = node['def']
abc_sit = abc['sit']
def_sit = def1['sit']
%w{abc_sit def_sit}.each do | client |
template "/etc/#{client}.sh" do
source 'tunnel.erb'
owner 'root'
group 'root'
variables ("#{client}") --> At this line I am getting error
end
end
The error I am getting when I run the chef-client:
option variables must be a kind of [Hash]! You passed "abc_sit"
As it says, you have to pass in a Hash. Perhaps something like variables myclient: client and then <%= #myclient %> in the template.

Where is the ruby function 'powershell' defined?

I am using the msutter DSC module for puppet. While reading through the source code, I come across code like this (in dsc_configuration_provider.rb):
def create
Puppet.debug "\n" + ps_script_content('set')
output = powershell(ps_script_content('set'))
Puppet.debug output
end
What file defines the powershell function or method? Is it a ruby builtin? A puppet builtin? Inherited from a class? I know that it is being used to send text to powershell as a command and gathering results, but I need to see the source code to understand how to improve its error logging for my purposes, because certain powershell errors are being swallowed and no warnings are being printed to the Puppet log.
These lines in file dsc_provider_helpers.rb may be relevant:
provider.commands :powershell =>
if File.exists?("#{ENV['SYSTEMROOT']}\\sysnative\\WindowsPowershell\\v1.0\\powershell.exe")
"#{ENV['SYSTEMROOT']}\\sysnative\\WindowsPowershell\\v1.0\\powershell.exe"
elsif File.exists?("#{ENV['SYSTEMROOT']}\\system32\\WindowsPowershell\\v1.0\\powershell.exe")
"#{ENV['SYSTEMROOT']}\\system32\\WindowsPowershell\\v1.0\\powershell.exe"
else
'powershell.exe'
end
Surely this defines where the Powershell executable is located, but gives no indication how it is called and how its return value is derived. Are stdout and stderr combined? Am I given the text output or just the error code? etc.
This is core Puppet logic. When a provider has a command, like
commands :powershell => some binary
That is hooked up as a function powershell(*args).
You can see it with other providers like Chocolatey:
commands :chocolatey => chocolatey_command
def self.chocolatey_command
if Puppet::Util::Platform.windows?
# must determine how to get to params in ruby
#default_location = $chocolatey::params::install_location || ENV['ALLUSERSPROFILE'] + '\chocolatey'
chocopath = ENV['ChocolateyInstall'] ||
('C:\Chocolatey' if File.directory?('C:\Chocolatey')) ||
('C:\ProgramData\chocolatey' if File.directory?('C:\ProgramData\chocolatey')) ||
"#{ENV['ALLUSERSPROFILE']}\chocolatey"
chocopath += '\bin\choco.exe'
else
chocopath = 'choco.exe'
end
chocopath
end
Then other locations can just call chocolatey like a function with args:
chocolatey(*args)

Why won't gradle Exec task run my command?

I have read around stackoverflow and the gradle forms, but I am still stumped. The ultimate goal here is that after I copy some files, I want to set the writable flag -- because 'copy' doesn't like overwriting read-only files on 'nix (huh...), nor can it be forced to do so (harumph!).
Here is the outline of what I have:
task setPermissions (type : Exec) {
executable = 'chmod -R +w'
}
// ... a little while later ...
task('somethingElse') << {
// ... unrelated stuff ...
def String targetDir = "$aVar/theTarget"
// >> TASK CALL <<
setPermissions {
commandLine = [executable + " $targetDir"]
}
// but that doesn't work... this does...
proc = Runtime.getRuntime().exec("chmod -R +w $deployDir")
proc.waitFor()
}
I have tried variations in "setPermissions".
Trial 1:
commandLine = 'chmod'
args = '-R', '+w'
In which case I appended the target directory to "args" when I called setPermissions.
Trial 2:
commandLine = 'chmod -R +w'
In which case I appended the target directory to "commandLine" when I called setPermissions. I also tried making it the only "args" value.
Trial 3:
commandLine = 'chmod', '-R', '+w'
In which case I appended the target directory to "commandLine" when I called setPermissions. I also tried making it the only "args" value.
So what am I doing wrong here that an Exec task won't run this properly, but the Rt.gR.exec() will?
You can't call a task from another task. You'll have to make one depend on the other, or call the Project.exec method from a task action. The syntax for configuring the exec method is exactly the same as for the Exec task.
PS: Have you tried to use Copy.fileMode instead of chmod?

How to change the prompt

I am trying to configure the prompt characters in ripl, an alternative to interactive ruby (irb). In irb, it is done using IRB.conf[:DEFAULT], but it does not seem to work with ripl. I am also having difficulty finding an instruction for it. Please guide to a link for an explanation or give a brief explanation.
Configuring a dynamic prompt in ~/.riplrc:
# Shows current directory
Ripl.config[:prompt] = lambda { Dir.pwd + '> ' }
# Print current line number
Ripl.config[:prompt] = lambda { "ripl(#{Ripl.shell.line})> " }
# Simple string prommpt
Ripl.config[:prompt] = '>>> '
Changing the prompt in the shell:
>> Ripl.shell.prompt = lambda { Dir.pwd + '> ' }
ripl loads your ~/.irbrc file, which
typically contains some irb specific
options (e.g. IRB.conf[:PROMPT]). To
avoid errors, you can install
ripl-irb, which catches calls to the
IRB constant and prints messages to
convert irb configuration to ripl
equivalents.
http://rbjl.net/44-ripl-why-should-you-use-an-irb-alternative

Resources