Equivalent of String.Format in a Chef/Bash Recipe - linux

looking for something similar to .Net string format in a chef recipe ie.
string phone = String.format("phone: {0}",_phone);
I have a Chef recipe where I need to build up a command string with 30 of these params so hoping for a tidy way to build the string, in principle Im doing this
a=node['some_var'].to_s
ruby_block "run command" do
block do
cmd = shell_out!("node mycommand.js #{a}; exit 2;")
end
end
When I try this I get the error
Arguments to path.join must be strings any tips appreciated

Chef runs in two phases:
Compile and Execute (see https://www.chef.io/blog/2013/09/04/demystifying-common-idioms-in-chef-recipes/ for more details).
Your variable assignment to a happens at compile time, e.g. when chef loads all recipes. The ruby block will be execute in execution mode at converge time and cannot access the variable a.
So the easiest solution might be putting the attribute into the ruby block:
ruby_block "run command with argument #{node['some_var']}" do
block do
shell_out!("node mycommand.js #{node['some_var']}")
end
end
However:
If you don't need to execute Ruby code, consider using the execute or bash resource instead.
Keep in mind, that you must have a unique resource name, if you're building some kind of loop around it. An easy way is to put something unique into the name ruby_block "something unique per loop iteration" do ... end
What I really don't understand is your exit code 2. This is an error code. It will make chef throw an exception each time. (shell_out! throws an exception if exit code != 0, see https://github.com/chef/chef/blob/master/lib/chef/mixin/shell_out.rb#L24-L28)
The resource will be executed on each chef run. This is probably not in your interest. Consider adding a guard (test), to prevent unnecessary execution, see https://docs.chef.io/resource_common.html#guards

Related

Return a String from a Windows Batch file

I want to find the target branch when a pull request is submitted on GitHub, in my Jenkins pipeline. To achieve this I am doing the following:
I am invoking a windows batch file from my Jenkinsfile, which in turn invokes a nodejs script. This script internally invokes GitHub APIs to get the target branch which is to be set on some variable in Jenkinsfile(code snippet given below):
Jenkinsfile
env.TARGET_BRANCH = bat "GetTargetBranchFromGit.bat ${env.BRANCH_NAME}"
BatchFile:
node getTargetBranchForPR.js %1
But unfortunately, the variable env.TARGET_BRANCH is not getting set to the target branch even though the nodejs script gets the right value. I am in fact not able to return the value from the batch file. Could someone please help me here?
#npocmaka mention is the right way: How to do I get the output of a shell command executed using into a variable from Jenkinsfile (groovy)?
Accodring to Jenkins' documentation.
returnStdout (optional) If checked, standard output from the task is
returned as the step value as a String, rather than being printed to
the build log. (Standard error, if any, will still be printed to the
log.) You will often want to call .trim() on the result to strip off a
trailing newline.
So your code should look like
env.TARGET_BRANCH = bat( script: "GetTargetBranchFromGit.bat ${env.BRANCH_NAME}",
returnStdout: true
).trim()
If you get back more than expected you probably need to parse it.

Throws error when passing argument with space in JAVA_OPTS in Linux

I am passing command line parameters to gatling script.
This works and executes my test in Windows operating system:
set JAVA_OPTS="-DuserCount=2 -DflowRepeatCount=3 -DdefinitionId=102168 -DtestServerUrl=https://someURL -DenvAuthenticationHeaderFromPostman="Basic UWRZm9aGwsxFsB1V7RXK0OlB5cmZvcm1hbmNldGVzdDE="
It works and takes input which is passed
**********************INPUT*************************************
User Count ====>> 2
Repeat Count ====>> 3
Definition ID ====>> 102168
Environment URL ====>> https://someURL
Authentication Header ====>> Basic UWRZm9aGwsxFsB1V7RXK0OlB5cmZvcm1hbmNldGVzdDE=
***********************************************************
I want to do this same thing on Linux System.
While if I use this command in Linux then it throws error or takes Null or Binary values as input
(Passing arguments with ./gatling.sh)
JAVA_OPTS="-DuserCount=2 -DflowRepeatCount=3 -DdefinitionId=102168 -DtestServerUrl='https://someURL' -DenvAuthenticationHeaderFromPostman='Basic UWRZm9aGwsxFsB1V7RXK0OlB5cmZvcm1hbmNldGVzdDE='" ./gatling.sh
Gives this error,
GATLING_HOME is set to /opt/gatling-charts-highcharts-2.0.3 Error:
Could not find or load main class
UWRZm9aGwsxFsB1V7RXK0OlB5cmZvcm1hbmNldGVzdDE='
Here the problem is the space given in argument of -DenvAuthenticationHeaderFromPostman='Basic UWRZm9aGwsxFsB1V7RXK0OlB5cmZvcm1hbm='.
What is the solution?
The problem is that the $JAVA_OPTS variable is probably not surrounded by quotes. See this question: Passing a space-separated System Property via a shell script doesn't work
The gatling guys clearly forgot to do that.
I would file a bug and/or just edit gatling.sh.
Ideally though you might just want to consider seeing if Gatling takes a properties file or some other way to configure.

How to skip Cucumber steps?

I have the scenario like:
Given I go to this page
When I type cucumber
And I click
Then I should see the text
And I should not see the line
If I run this scenario it will execute all the 5 steps. But I want to skip the 4th step (Then I should see the text) and execute the 5th step.
Please give me your suggestions. Thanks in advance. :)
TL;DR - don't do it - you're (probably) getting it wrong. And you can't (easily) do it. As Aslak wrote (one of Cucumber main creators):
A step can have the following results:
undefined (no matching stepdef)
pending (a matching stepdef that throws PendingException)
passed (a matching stepdef that doesn't throw anything)
failed (a matching stepdef that throws an exception that isn't PendingException)
skipped (a step following a step that threw any exception (undefined, pending or failed))
What you're asking for is a new kind of result - ignored. It could be
implemented by throwing an IgnoredException. This would mean that
skipped would have to be changed to: (a step following a step that
threw any exception (undefined, pending or failed) - unless the
exception was IgnoredException)
I'm not sure I like this. It sounds like more complicated than it
needs to be. You already have the necessary information that something
is amiss - your step will either fail or be pending. I don't see the
value in continuing to execute the following steps. You still have to
implement the failing/pending step.
As long as you're reminded that "there is work to be done here" I
don't think it's wortwhile complicating Cucumber to tell you what kind
of work needs to be done...
Aslak
Whole discussion is here: http://comments.gmane.org/gmane.comp.programming.tools.cucumber/10146
I have had to skip steps conditionally based on environments. I used next to skip steps. Here is an example on how to do what you wanted.
Then /^I should see the text/$ do
next if #environment == 'no text'
...
<The actual step definition>
...
end

cant create arrays in while loop or if statement?

when I try to create arrays in my script I get errors.
id[1]=string2; would generate error id[1]=string2: not found
I'm guessing it has something to do with the fact that im in a if statement or while loop since the use []? I'm running a VM so attached is a pic of the script thus far the array at top a[1]=string; generates no errors but the one in the logic id[1]=string2; does.
Posting as an answer so this question can be marked as resolved:
Your script is being executed by sh, not bash. Add a correct shebang line as the first line of the script file:
#!/bin/bash

How can I make cucumber run all the steps (not skip them) even if one of them fails?

I am using Cucumber with RubyMine, and I have a scenario with steps that verify some special controls from a form (I am using cucumber for automation testing). The controls don't have anything to do with each other, and there is no reason for the steps to be skipped if one in front of them fails.
Does anyone know what configurations or commands should I use to run all the steps in a scenario even if they all fail?
I think the only way to achieve desired behavior (which is quite uncommon) is to define custom steps and catch exceptions in it yourself. According to cucumber wiki step is failed if it raises an error. Almost all default steps raise error if they can't find or interact with an element on the page. If you'll catch this exceptions the step will be marked as passed, but in rescue you can provide custom output. Also I recommend you to carefully define exceptions you want to catch, I think if you're Ok if selenium can't find an element on the page rescue only from ElementNotFound exceptions, don't catch all exceptions.
I've seen a lot of threads on the Web about people wanting to continue steps execution if one failed.
I've discussed with Cucumber developers: they think this is a bad idea: https://groups.google.com/forum/#!topic/cukes/xTqSyR1qvSc
Many times, scenarios can be reworked to avoid this need: scenarios must be split into several smaller and independent scenarios, or several checks can be aggregated into one, providing a more human scenario and a less script-like scenario.
But if you REALLY need this feature, like our project do, we've done a fork of Cucumber-JVM.
This fork let you annotate steps so that when they fail with a determined exception, they will let let next steps execute anyway (and the step itself is marked as failed).
The fork is available here:
https://github.com/slaout/cucumber-jvm/tree/continue-next-steps-for-exceptions-1.2.4
It's published on the OSSRH Maven repository.
See the README.md for usage, explanation screenshot and Maven dependency.
It's only available for the Java language, tough: any help is welcome to adapt the code to Ruby, for instance. I don't think it will be a lot of work.
The question is old, but hopefully this will be helpful. What I'm doing feels kind of "wrong", but it works. In your web steps, if you want to keep going, you have to catch exceptions. I'm doing that primarily to add helpful failure messages. I'm checking a table full of values that are identified in Cucumber with a table having a bunch of rows like:
Then my result should be:
| Row Identifier | Column Identifier | Subcolum Identifier | $1,247.50 |
where the identifiers make sense in the application domain, and name a specific cell in the results table in a human-friendly way. I have helpers that convert the human identifiers to DOM IDs, which are used to first check whether the row I'm looking for exists at all, then look for the specific value in a cell in that row. The default failure message for a missing row is clear enough for me (expected to find css "tr#my_specific_dom_id" but there were no matches). But the failure message for checking specific text in a cell is completely unhelpful. So I made a step that catches the exception and uses the Cucumber step info and some element searching to get a good failure message:
Then /^my application domain results should be:$/ do |table|
table.rows.each do |row|
row_id = dom_id_for(row[0])
cell_id = dom_id_for(row[0], row[1], row[2])
page.should have_css "tr##{row_id}"
begin
page.should have_xpath("//td[#id='#{cell_id}'][text()=\"#{row[3].strip.lstrip}\"]")
rescue Capybara::ExpectationNotMet => exception
# find returns a Capybara::Element, native returns a Selenium::WebDriver::Element
contents = find(:xpath, "//td[#id='#{cell_id}']").native.text
puts "Expected #{ row[3] } for #{ row[0,2].join(' ') } but found #{ contents } instead."
#step_failures_were_rescued = true
end
end
end
Then I define a hook in features/support/hooks.rb like:
After do |scenario|
unless scenario.failed?
raise Capybara::ExpectationNotMet if #step_failures_were_rescued
end
end
This makes the overall scenario fail, but it masks the step failure from Cucumber, so all the step results are green, including the ones that aren't right. You have to see the scenario failure, then look back at the messages to see what failed. This seems kind of "bad" to me, but it works. It's WAY more convenient in my case to get the expected and found values listed in a domain-friendly context for the whole table I'm checking, rather than to get a message like "I looked for "$123.45" but I couldn't find it." There might be a better way to do this using the Capybara "within" method. This is the best I've come up with so far though.

Resources