I'm trying to create a minitest for chef (minitest::spec) and I'm a little lost at how to accomplish what I want in ruby.
What I want to do is have the code run the 'date' command and then check if the output contains 'UTC'.
I have this so far, but I don't know how to check the output for 'true':
it "uses the correct timezone" do
timezone_check = shell_out("date")
timezone_check.to_s.include?('UTC')
end
I tried to use .must_output, but I don't know how to incorporate it. Is this even the best way to accomplish what I want?
Any input is appreciated!
Thanks.
EDIT: I have now tried this:
it "uses the correct timezone" do
date_input = `date`
proc { puts date_input.to_s }.must_output /UTC/
end
but it results in this:
Failure:
test_0002_uses_the_correct_timezone(recipe::base::default) [/var/chef/minitest/base/default_test.rb:18]:
In stdout.
--- expected
+++ actual
## -1 +1,2 ##
-/UTC/
+"Fri Apr 19 17:50:27 UTC 2013
+"
Testing shell_out requires you to test against stdout
it "uses the correct timezone" do
timezone_check = shell_out("date")
timezone_check.stdout.must_match /UTC/
end
For more examples check out Cookbook Integration Testing
Wrap it in a proc and try using must_output. The test would probably look like:
it "uses the correct timezone" do
proc { timezone_check = shell_out("date") }.should_output /UTC/
end
Not entirely sure from the documentation that the should_output method will accept a pattern, but if you can write the test such that you know precisely the entire output expected, then you can simply test against the full expected string. E.g.
it "uses the correct timezone" do
proc { timezone_check = shell_out("date") }.should_output("Fri Apr 19 12:33:13 CDT 2013")
end
Related
I am trying to increment the value and use in another resource dynamically in recipe but still failing to do that.
Chef::Log.info("I am in #{cookbook_name}::#{recipe_name} and current disk count #{node[:oracle][:asm][:test]}")
bash "beforeTest" do
code lazy{ echo #{node[:oracle][:asm][:test]} }
end
ruby_block "test current disk count" do
block do
node.set[:oracle][:asm][:test] = "#{node[:oracle][:asm][:test]}".to_i+1
end
end
bash "test" do
code lazy{ echo #{node[:oracle][:asm][:test]} }
end
However I'm still getting the error bellow:
NoMethodError ------------- undefined method echo' for Chef::Resource::Bash
Cookbook Trace: ---------------
/var/chef/cache/cookbooks/Oracle11G/recipes/testSplit.rb:3:in block (2 levels) in from_file'
Resource Declaration: ---------------------
# In /var/chef/cache/cookbooks/Oracle11G/recipes/testSplit.rb
1: bash "beforeTest" do
2: code lazy{
3: echo "#{node[:oracle][:asm][:test]}"
4: }
5: end
Please can you help how lazy should be used in bash? If not lazy is there any other option?
bash "beforeTest" do
code lazy { "echo #{node[:oracle][:asm][:test]}" }
end
You should quote the command for the interpolation to work; if not, ruby would search for an echo command, which is unknown in ruby context (thus the error you get in log).
Warning: lazy has to be for the whole resource attribute; something like this WON'T work:
bash "beforeTest" do
code "echo node asm test is: #{lazy { node[:oracle][:asm][:test]} }"
end
The lazy evaluation takes a block of ruby code, as decribed here
You may have a better result with the log resource like this:
log "print before" do
message lazy { "node asm test is #{node[:oracle][:asm][:test]}" }
end
I've been drilling my head solving this problem until I came up with lambda expressions. But yet just using lambda didn't help me at all. So I thought of using both lambda and lazy evaluation. Though lambda is already lazy loading, when compiling chef recipe's, the resource where you call the lambda expression is still being evaluated. So to prevent it to being evaluated (somehow), I've put it inside a lazy evaluation string.
The lambda expression
app_version = lambda{`cat version`}
then the resource block
file 'tmp/validate.version' do
user 'user'
group 'user_group'
content lazy { app_version.call }
mode '0755'
end
Hope this can help others too :) or if you have some better solution please do let me know :)
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)
I'm currently trying to use ExecJS to run Handlebars for one of the product I work on (note: I know the handlebars.rb gem which is really cool and I used it for some times but there is issues to get it installed on Windows, so I try another homemade solution).
One of the problem I'm having is that the Javascript context is not kept between each "call" to ExecJS.
Here the code where I instantiate the #js attribute:
class Context
attr_reader :js, :partials, :helpers
def initialize
src = File.open(::Handlebars::Source.bundled_path, 'r').read
#js = ExecJS.compile(src)
end
end
And here's a test showing the issue:
let(:ctx) { Hiptest::Handlebars::Context.new }
it "does not keep context properly (or I'm using the tool wrong" do
ctx.js.eval('my_variable = 42')
expect(ctx.js.eval('my_variable')).to eq(42)
end
And now when I run it:
rspec spec/handlebars_spec.rb:10 1 ↵
I, [2015-02-21T16:57:30.485774 #35939] INFO -- : Not reporting to Code Climate because ENV['CODECLIMATE_REPO_TOKEN'] is not set.
Run options: include {:locations=>{"./spec/handlebars_spec.rb"=>[10]}}
F
Failures:
1) Hiptest::Handlebars Context does not keep context properly (or I'm using the tool wrong
Failure/Error: expect(ctx.js.eval('my_variable')).to eq(42)
ExecJS::ProgramError:
ReferenceError: Can't find variable: my_variable
Note: I got the same issue with "exec" instead of "eval".
That is a silly example. What I really want to do it to run "Handlebars.registerPartial" and later on "Handlebars.compile". But when trying to use the partials in the template it fails because the one registered previously is lost.
Note that I've found a workaround but I find it pretty ugly :/
def register_partial(name, content)
#partials[name] = content
end
def call(*args)
#context.js.call([
"(function (partials, helpers, tmpl, args) {",
" Object.keys(partials).forEach(function (key) {",
" Handlebars.registerPartial(key, partials[key]);",
" })",
" return Handlebars.compile(tmpl).apply(null, args);",
"})"].join("\n"), #partials, #template, args)
end
Any idea on how to fix the issue ?
Only the context you create when you call ExecJS.compile is preserved between evals. Anything you want preserved needs to be part of the initial compile.
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
I'm running the following commands
set full_pin_name [format "%s %s" $top_cell $encoded_name]
puts "full_pin_name is $full_pin_name"
and I get the following error:
full_pin_name is invalid command name "A" B
when top_cell equals A and encoded_name equals B.
Why is this happening?
I suspect the problem is with your $top_cell variable, which has the value invalid command name "A". To check, try the following line before your format line:
puts ">$top_cell<"
If indeed, $top_cell value has a problem, you can then trace back to the last set command. Let us know if it fixes your problem, or we might try some other approaches.
Try repeating this in a plain Tcl shell, it works. Something is different in your Tcl shell.
Try
info body set
and
info body format
If either report something other than set isn't a procedure or format isn't a procedure then you have your culprit.
May be this code runs in a namespace which has the set command defined in it?
To demonstrate:
% namespace eval foo {
proc set args {
puts hey!
}
proc whatever {top_cell encoded_name} {
set full_pin_name [format "%s %s" $top_cell $encoded_name]
puts "full_pin_name is $full_pin_name"
}
}
% ::foo::whatever A B
hey!
can't read "full_pin_name": no such variable
%
As far as I can tell without a TCL interpreter here it should work assuming a normal interpreter with format defined. so it looks like maybe format has been renamed or doesn't exist as a command in the interpreter you are using?
To get you going you don't really need format to join strings anyway
set fill_pin_name "$top_cell $encoded_name"
should so what you need
Maybe your code looks like this:
set encoded_name B
if { [catch {[A]} top_cell]} {
set full_pin_name [format "%s %s" $top_cell $encoded_name]
puts "full_pin_name is $full_pin_name"
}
The result is:
full_pin_name is invalid command name "A" B