Run command after gem install from gem root folder - ruby

I'm deploying a Sinatra app as a gem. I have a command that starts the app as a service.
We are using chef to manage our deployments.
How can I run the command to start the app service but only after it's fully installed (including run-time dependencies)?
I've tried Googling for trying to run a post-install script but I haven't found anything that is of use or concrete without some complicated 'extconf.rb' work around
I would prefer not to use an execute resource if I can help it.
EDIT: I tried what was suggested but it breaks thins in way that causes berkshelf not to work in our pipeline.
Here's the code I'm using:
execute "run-service:post_install" do
cwd (f = File.expand_path(__FILE__).split('/')).shift(f.length - 3).join('\\')
timeout 5
command "bundle && rake service:post_install"
# action :nothing
# subscribes :run, "gem_package[gem_name]" , :delayed
end
It doesn't matter if I un-comment or not the last two lines, it just breaks things but if i take out the whole thing it stops breaking things. Obviously I'm doing something wrong but I'm not sure what.
EDIT:
IT's the command itself that breaks it, when I change command to ls and action to :run, it breaks.
EDIT:after changing the command path around a bit I managed to get it to spit out a usable error, it was trying to run the command from chef cook books path, so I've (hopefully) forced it to use the correct path.

Why do you not want to use an execute resource? That is exactly what it is for, running commands from Chef. Chef obeys the order of the resources, so if you have a gem_package followed by an execute they will run in that order.

So, In the end I decided to try using the service resource because it allows you to set start, and stop commands.
The code that I used is :
service service_name do
init_command ("#{%x(gem env gemdir).strip.gsub('/','\\')}\\gems\\gem_name-#{installing_version}")
start_command "rake service:start"
stop_command "rake service:stop"
reload_command "rake service:reload"
restart_command "rake service:restart"
supports start: true, restart: true, reload: true
action [:enable,:start]
end
I'm still having problems but this is of a different sort.

Related

How to use a Chef Windows reboot resource to reboot only once

I'm currently attempting to use the reboot resource in a chef resource:
reboot 'ADS Install Complete' do
action :nothing
reason 'Cannot continue Chef run without a reboot.'
only_if {reboot_pending?}
end
...
execute 'Initialize ADS Configuration INI' do
command "\"#{node["ads-tfs-ini"]["tfsconfig_path"]}\" unattend \/create \/type:#{node["ads-tfs-ini"]["Scenario"]} \/unattendfile:\"#{node["ads-tfs-ini"]["unattend_file_path"]}\""
only_if { ! "#{ENV['JAVA_HOME']}".to_s.empty? }
notifies :request_reboot, 'reboot[ADS Install Complete]', :delayed
end
I am getting an endless loop of reboots (client reboots-->chef client runs-->chef client reruns the run_list--client reboots-->...). How can I just reboot once?
You could add some validation to check whether the computer has been rebooted once.
ruby_block "reboot" do
unless File.exist?("C:\reboot") do
block do
Chef::Util::FileEdit.new('C:\reboot').write_file
Chef::ShellOut.new("shutdown /r").run_command
end
end
end
This solution isn't really elegant, but it should work. The reboot is inside the ruby block which will only run if C:\reboot DOESN'T exist. If the file doesn't exist, the block will create the file and then call the reboot. On the second chef run, the file will exist so the reboot will not be triggered.
Here is the documention regarding ruby_block
from reboot chef resource:
Use the reboot resource to reboot a node, a necessary step with some installations on certain platforms. This resource is supported for use on the Microsoft Windows, macOS, and Linux platforms.
reboot 'name' do
action :reboot_now
end
Your only_if guard in the execute resource makes execute resource run, if ENV['JAVA_HOME'] is not empty. Very likely, that this environment variable is set and that's why your execute resource is run every time Chef runs, and triggers the reboot.
My guess, is you just actually need an opposite, run the resource, only if the variable is empty. For that you can just remove the ! from the line.
only_if { ENV['JAVA_HOME'].to_s.empty? }
If my previous guess is wrong, then you need to change your only_if guard to something more robust. From the command line, I understand you create some configuration files, so you don't need to run execute resource, when you config files already exist:
not_if { ::File.exist?('/path/to/file/created/by/command') }

Testing a Jekyll site with rspec and capybara, getting a bizarre race-case on rspec start

So check this out: it appears as though, upon running bundle exec rspec, there's a race between jekyll serve and puma/rspec's boot up. Sometimes I run the command, and my tests run fine. Other times, I get the error for each of my spec files: cannot load such file -- /path/to/project/sitename_jekyll/_layouts/spec/form_spec.rb which is interesting cause that's not where my spec files are located. They're in /path/to/project/sitename_jekyll/spec/form_spec.rb.
What's crazy is that I can literally just re-run the command over and over and over again and sometimes it'll go through and run the spec tests in the correct location, and sometimes it'll look for them in _layouts and error out. It probably runs correctly maybe once out of ever three or five attempts. All the other times I get the following errors:
Here's what my spec_helper.rb looks like: https://gist.github.com/johnhutch/2cddfafcde0485ff021501d5696c0c2d
And here's an example test file:
https://gist.github.com/johnhutch/a35d15c170f5fd9ca07998bf035d111d
My .rspec only contains two lines:
--color
--require spec_helper
And here's the output, both successful and unsuccesful, back to back:
https://gist.github.com/johnhutch/7927d609170ef5c70a595735502b128d
HEEELLLLLP!
This sounds like jekyll is changing the current directory while building the site, which since it is being run in a thread also affects the tests RSpec is trying to run (See https://bugs.ruby-lang.org/issues/9785 for why Dir.chdir is not threadsafe) - leading to attempts to load things from incorrect locations.
A potential solution to this would be to wait for the Jekyll site to be built before actually running your tests. A comment in your spec_helper seems to state that someone thought passing force_build: true would do this but from a quick perusal of the jekyll-rack code I don't think that's true and you actually need to wait for compiling? to return false (v 0.5) (complete? to return true in the current master branch) to ensure building has finished (as well as passing force_build). This could either be done in a loop sleeping and checking (simpler)
sleep 0.1 while <jekyll app>.compiling?
or (if using the master branch) via the mutex/conditional Rack::Jekyll exposes like in its test suite - https://github.com/adaoraul/rack-jekyll/blob/master/test/helper.rb#L49
Note: Also check my comment about your tests that aren't actually testing anything.
As per Thomas Walpole's super helpful responses this ended up working:
sleep 0.1 while Capybara.app.compiling?
inserted right after:
51 Capybara.app = Rack::Jekyll.new(force_build: true)
in my spec_helper.rb
Thanks again, Thomas!

Puppet: generate statement fails when trying to retrieve default path of an executable

I have built a stanza to remove a ruby gem package from our servers. The problem is that the ruby gem executable is installed in different paths on the servers, so on one server it could be in /opt/ruby/bin/gem on other servers it's in /usr/local/rvm/rubies/ruby-2.0.0-p353/bin/gem
My stanza uses the generate function in puppet to pull out the default ruby gem installation as follows:
$ruby_gem_location = generate('which', 'gem')
exec { "remove-remote_syslog":
command => "gem uninstall remote_syslog",
path => "$ruby_gem_location:/opt/ruby/bin:/usr/bin:/usr/sbin",
onlyif => "$ruby_gem_location list|grep remote_syslog"
}
When I run puppet agent I get the following error:
Generators must be fully qualified at ****redacted*
I have also tried to provide a default path for the which command as follows:
$ruby_gem_location = generate('/usr/bin/which', 'gem')
and now the error says : Could not evaluate: Could not find command '/usr/bin/gem
I checked the target server and the gem command is in
/usr/local/rvm/rubies/ruby-2.0.0-p353/bin/gem
What am I doing wrong?
How can I pull out the default ruby gem location on our servers?
Thank you in advance
Your code
$ruby_gem_location = generate('/usr/bin/which', 'gem')
will generate a full path to your gem command (if it succeeds). From the result you describe, I think it is generating '/usr/bin/gem', which is perhaps a symlink to the real gem command. You are putting that into your command path instead of just the directory part, and that will not be helpful. It is not, however, the source of the error message you report.
The real problem here is that generate(), like all DSL fucntions, runs during catalog building. I infer from your results that you are using a master / agent setup, so generate() is giving you a full path to gem -- evidently /usr/bin/gem -- on the master. Since the whole point is that different servers have gem installed in different places, this is unhelpful. The actual error message arises from an attempt to execute your onlyif command with the wrong path to gem.
Your best way forward is probably to create a custom fact with which each node can report the appropriate location of the gem binary. You can then use that fact's value in your Exec, maybe:
exec { "remove-remote_syslog":
command => "$::ruby_gem_path uninstall remote_syslog",
onlyif => "$::ruby_gem_path list | grep remote_syslog"
}
Note that you don't need a path attribute if you give a complete path to the executable in the first place.
Details on creating the $::ruby_gem_path custom fact depend on a number of factors, and in their full generality they are rather too broad for SO, but PL provides good documentation.

how can I run test files on Windows using rake?

UPDATE: when I run rake test from root, I get:
C:\workspace\faker>rake test
DL is deprecated, please use Fiddle
C:/RailsInstaller/Ruby2.1.0/bin/ruby.exe -w -I"lib;test;." -I"C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/rake-10.4.2/lib" "C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/rake-10.4.2/lib/rake/rake_test_loader.r
b" "test/test_array_sample_method_compat.rb" "test/test_avatar.rb" "test/test_en_au_ocker_locale.rb" "test/test_en_ca_locale.rb" "test/test_en_locale.rb" "test/test_en_ug_locale.rb" "test/test_en_us_locale.rb" "test/test_es_l
ocale.rb" "test/test_faker.rb" "test/test_faker_app.rb" "test/test_faker_bitcoin.rb" "test/test_faker_book.rb" "test/test_faker_business.rb" "test/test_faker_city.rb" "test/test_faker_code.rb" "test/test_faker_color.rb" "test
/test_faker_commerce.rb" "test/test_faker_company.rb" "test/test_faker_date.rb" "test/test_faker_hacker_talk.rb" "test/test_faker_internet.rb" "test/test_faker_lorem.rb" "test/test_faker_name.rb" "test/test_faker_number.rb" "
test/test_faker_shakespear.rb" "test/test_faker_shakespeare.rb" "test/test_faker_slack_emoji.rb" "test/test_faker_street.rb" "test/test_faker_team.rb" "test/test_faker_time.rb" "test/test_faker_university.rb" "test/test_flexi
ble.rb" "test/test_helper.rb" "test/test_locale.rb" "test/test_pl_locale.rb" "test/test_uk_locale.rb"`
I don't fully understand what rake is doing at this point, but the system hangs infinitely. What am I missing?
So I have built some added functionality for the faker gem, and want to run the tests I wrote before submitting a pull request. However, all my attempts to run the existing tests, and my new tests, have failed. I am worried that it is a Windows machine related issue.
I have tried running rake test:units but it gives me an error and then hangs, while also ringing the Bell on my system 5 times. Strange right?
I have also tried running bundle exec rspec spec, but no tests are found becasue they are not RSpec unit tests, or at least not in the right location.
To see how the gem is formatted, check it out at the repo
All the test files, including my new one, live in the test directory. But for the life of me, I can't run them.
I tried this and works fine:
bundle install
bundle exec ruby test

RSpec Autotest loops with failures, doesn't work when exceptions are added

I've been playing around with autotest trying to make it work all day.. but am having some problems...
I've been following https://github.com/rspec/rspec/wiki/autotest, I'm running with:
Ruby 1.9.3-p194
rspec 2.10.0
ZenTest 4.8.1
I also created a .rspec file.
So with this setup, I run autotest, and it works - my test runs, it passes, hooray!. When I stick a failure into my test e.g. false.should == true, then the test starts looping, over and over again.
what happens is that it's an integration test, and I'm writing to an sqlite db. If I run find . -mmin -1 then I'm able to see that my db folder has changed - so I figured this is the problem.
So I edit .autotest and add the following:
Autotest.add_hook :initialize do |autotest|
%w{db}.each { |exception| autotest.add_exception(exception) }
false
end
But now when I run autotest, it just says the following:
loading autotest/rspec2
and that's it, it won't do anything anymore. Previously the output was:
loading autotest/rspec2
/home/me/.rbenv/versions/1.9.3-p194/bin/ruby -rrubygems -S '/home/me/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/rspec-core-2.10.1/exe/rspec' ``--tty '/home/me/Workspace/myproject/spec/integration/db/lead_spec.rb'
and then it'd run my test and show the result...
Anyone know what could be going on? it's very frustrating, and I feel like I've come to a road block....
Thanks for your help!
Autotest checks if defined exceptions match any part of the filename. Your spec has db in it's path so it is ignored by autotest.
If you want to ignore db folder, then do the following:
Autotest.add_hook :initialize do |a|
a.add_exception %r{^\./db}
end

Resources