Use Vagrant trigger to execute bash script on host - bash

I use Vagrant to start my testing environment. Sadly I have to retrieve information (passwords) before spinning up my Vagrant box. So far I use Vagrant-Triggers to do this and have multiple run "do something" commands.
IS
[:up, :provision].each do |cmd|
config.trigger.before cmd, stdout: true do
run "rm -rf #{cookbooks_path}"
run "mkdir -p #{cookbooks_path}"
run "touch fileX"
run "touch fileY"
run "touch fileZ"
end
end
How can I move all my commands to one batch file which I then only
include?
SHOULD
[:up, :provision].each do |cmd|
config.trigger.before cmd, stdout: true do
include_script "Vagrant_trigger_before.sh"
end
end
Thank you for your help!

You can run your script directly using the run instructions
[:up, :provision].each do |cmd|
config.trigger.before cmd, stdout: true do
run "Vagrant_trigger_before.sh"
end
end

After trigger plugin was merged to vagrant mainline, the syntax seems to be changed to
config.trigger.before :up, :provision do |trigger|
trigger.run = {inline: "Vagrant_trigger_before.sh"}
end
Ref: https://www.vagrantup.com/docs/triggers/configuration#inline

Besides this being a quite old thread, some useful hints for others who end up here:
As #frederic-henri and #lin-n pointed out, you can use trigger.run and current trigger syntax to execute a script on the host before or after specific Vagrant commands
trigger.run accepts arguments for the script
Summing up (not tested):
config.trigger.before :up, :provision do |trigger|
trigger.run do |run|
run.args = cookbooks_path
run.path = <Script>
end
end

Related

chef-solo getting logs from a bash script

I am executing a shell script via chef like below
execute 'Run postgres data migration' do
command '/home/ubuntu/build-target/infra-base/psql10_migration.sh'
live_stream true
action :run
only_if { ::File.exist?('/home/ubuntu/build-target/infra-base/psql10_migration.sh') }
end
My chef logs are directed to a file (log_location '/var/log/arkin/chef-run.log' )
Right now I am not getting any logs from the bash script psql10_migration.sh. Can someone let me know how can I get the logs from the bash script ?
Used in bash redirection like below
execute 'Run postgres data migration' do
command '/home/ubuntu/build-target/infra-base/psql10_migration.sh >> /home/ubuntu/logs/psql10-migration.log 2>&1'
action :run
only_if { ::File.exist?('/home/ubuntu/build-target/infra-base/psql10_migration.sh') }
end

Strange behavior with ruby_block resource in Chef

I have two ruby blocks at the end of a recipe:
ruby_block 'set permissions for app dir' do
block do
require 'fileutils'
FileUtils.chown_R 'user01', 'user01', '/mnt/app/'
end
action :run
end
ruby_block 'configure node app session' do
block do
cmd = "sudo su - user01 -c \"/mnt/app/http-app-/bin/app create /mnt/app/http-app/#{node['hostname']}\" && sudo su -c 'systemctl enable app' && sudo su -c 'systemctl start app'"
exec(cmd)
end
action :run
not_if "stat -c %U /mnt/app/#{node['hostname']} |grep app"
end
A couple strange things are happening. One, I cannot add any code after the last block... it will not run if added. Two, when the cookbook runs the recipe never ends with if the run failed or was successful. Bootstrapping the system a second time will prove to finish successful... but ssh'ing to the box and running chef-client comes back with an empty run list.
Can anyone explain this behavior? How can i fix it?
exec() is not what you think. That's a Ruby core method which calls the actual exec() syscall, which replaces the current process with something new. What you want is our shell_out!() helper which runs a subcommand and returns and object with the results.

How to achieve idempotence when we execute bash script in ruby/knife environment?

I am trying to execute bash script in knife/Ruby environment. For example:
cookbook_file "test.sh" do
path "/tmp/test.sh"
mode "755"
action :create
end
bash "execute test.sh on #{nodeName}" do
code <<-EOH
sh test.sh arg1 arg2
EOH
#only_if { false }
end
How can I use only_if or not_if? So when we execute second time and the contents of "test.sh" is not changed, it should skip execution. I am getting this:
* cookbook_file[test.sh] action create (up to date)
but it still executes second time, third time...
You wouldn't use a guard, instead you would use a notification:
execute 'run test' do
action :nothing
command 'bash /tmp/test.sh arg1 arg2'
end
cookbook_file "test.sh" do
path "/tmp/test.sh"
mode "755"
notifies :run, 'execute[run test]', :immediately
end
Notifications trigger when a resources updates, so any time the cookbook file changes, it will run the execute. Also you want to be using execute instead of bash or script because you are running a command rather than an inline script file.

How do I to run a command in Linux as a Ruby script?

Let's say I have some terminal commands like:
sudo mycommand1
mycommand2
#.....
What should I do run them via ruby script (not bash) in Ubuntu?
UPDATE:
I have a ruby script:
def my_method1()
#calculating something.....
end
def method2(var1, var2)
#how do I sudo mycommand1 and any other Lunix command from here?
end
def method3(var4)
#calculating something2....
end
You can do system, exec, or place the command in backticks.
exec("mycommand") will replace the current process so that's really only pratical at the end of your ruby script.
system("mycommand") will create a new process and return true if the command succeeded and nil otherwise.
If you need to use the output of your command in your Ruby script use backticks:
response = 'mycommand`
There are many questions on SO that answer this. However you can run a command in many ways using system, exec, (backticks), %x{} or using open3. I prefer to use open3 -
require 'open3'
log = File.new("#{your_log_dir}/script.log", "w+")
command = "ls -altr ${HOME}"
Open3.popen3(command) do |stdin, stdout, stderr|
log.puts "[OUTPUT]:\n#{stdout.read}\n"
unless (err = stderr.read).empty? then
log.puts "[ERROR]:\n#{err}\n"
end
end
If you want to know more about other options you can refer to Ruby, Difference between exec, system and %x() or Backticks for links to relevant documentation.
You can try these approaches:
%x[command]
Kernel.system"command"
run "command"
make some file.rb with:
#!/path/to/ruby
system %{sudo mycommand1}
system %{mycommand2}
and the chmod the file with exec permissions (e.g. 755)
It you need to pass variables between the two commands, run them together:
system %{sudo mycommand1; \
mycommand2}

Chef shell script not being run

I am using Chef on Scalarium to download an agent and run various commands on it. What I'm attempting is to write a shell script in the recipe to perform this.
file "/etc/profile.d/blah.sh" do
content <<-EOH
sudo -sH
<Retrieve file and run some commands>
EOH
end
When I run the recipe in Scalarium, no errors occur, but the commands aren't run either. There's no errors in the commands themselves, as I've run them on my computer.
The recipe is definitely read, as the Chef logs contain Processing file[/etc/profile.d/blah.sh] on blah.localdomain.
I've never used Chef before, do I need to do something else to tell it to execute the shell script?
Perhaps you want something like:
file "/etc/profile.d/blah.sh" do
mode 0500
content <<-EOH
sudo -sH
<Retrieve file and run some commands>
EOH
end
execute "/etc/profile.d/blah.sh"
Or, you can put the file retrieval and running of commands directly into your chef recipe:
remote_file "/path/to/where/the/file/should/be/saved" do
source "https://example.com/path/to/where/the/file/comes/from"
end
execute "first command"
execute "second command"

Resources