I am having a chef recipe with the following bash block -
bash "run_bash" do
user node[:value1][:user]
group node[:value1][:group]
cwd node[:value1][:install_dir] + '/tools/bin'
code <<-EOH
export MW_HOME=#{node[:value1][:mw_install_dir]}
export JAVA_HOME=#{node[:value1][:install_dir]}
export ORACLE_HOME=#{node[:value1][:install_dir]}
/usr/bin/expect -c 'spawn ./idmConfigTool.sh -configOAM input_file=#{Chef::Config[:file_cache_path]}/config.props
expect "Enter ID Store Bind DN password : "
send "#{OrcladminPassword}\r"
expect "Enter User Password for IDSTORE_PWD_SOFTWAREUSER: "
send "#{LDAPPassword }\r"
expect "Confirm User Password for IDSTORE_PWD_APPSOFTWAREUSER: "
send "#{AppLDAPPassword }\r"
expect "Enter User Password for IDSTORE_PWD_APP2ADMINUSER: "
send "#{App2AdminPassword }\r"
expect "Confirm User Password for IDSTORE_PWD_APP3ADMINUSER: "
send "#{App3AdminPassword}\r"
sleep 240
expect eof'
EOH
I am trying to run this recipe with chef-solo.So redundantly this recipe will run.
I need a solution to make this bash block to be idempotent. There are guard statements like not_if,only_if etc. But i could not find a way to implement those guards here.
I thought of one solution which is,Once this bash block ran successful , i can find the time stamp and compare it with the current time stamp when the next run is happening. If those didn't match i can ignore running it.This is just a brute force work a round i can think.
Kindly provide a better optimal solution for this scenario.
I'd go with a template an using notifications:
your_cookbook/templates/default/script.erb
:
#!/bin/bash
export MW_HOME=<%= node[:value1][:mw_install_dir] %>
export JAVA_HOME=<%= node[:value1][:install_dir] %>
export ORACLE_HOME=<%= node[:value1][:install_dir]}
/usr/bin/expect -c 'spawn ./idmConfigTool.sh -configOAM input_file=<%=
Chef::Config[:file_cache_path] %>/config.props
expect "Enter ID Store Bind DN password : "
send "<%= @OrcladminPassword %>\r"
expect "Enter User Password for IDSTORE_PWD_SOFTWAREUSER: "
send "<%= @LDAPPassword %>\r"
expect "Confirm User Password for IDSTORE_PWD_APPSOFTWAREUSER: "
send "<%= @AppLDAPPassword %>\r"
expect "Enter User Password for IDSTORE_PWD_APP2ADMINUSER: "
send "<%= @App2AdminPassword %>\r"
expect "Confirm User Password for IDSTORE_PWD_APP3ADMINUSER: "
send "<%= @App3AdminPassword %>\r"
sleep 240
expect eof
you_cookbook/recipes/default.rb
:
execute 'my_installer' do
command '/usr/local/bin/my_script'
action :noting # For it not to run on each converge by default
end
template '/usr/local/bin/my_script' do
source 'script.erb'
mode '0600'
variables(
'OrcladminPassword' => <how you set the value>,
'LDAPPassword' => <...>,
'AppLDAPPassword' => <...>,
'App2AdminPassword' => <...>,
'App3AdminPassword' => <...>
)
notifies :run,execute[my_installer]
end
You may add a , :immediately
at the end of the notifies line to trigger the execution just have the template have been rendered.
This way chef will trigger the execute resource only when the template change.
This doesn't take in account cases where your install may not work and chef won't retry it in this case, the installation will stay failed.
All in all I would work with the product editor to have a kind of package to avoid this kind of brittle install.