power-shell script in chef keeps being recognized as ruby code - ruby

The initial problem I Was trying to solve was that chefDK version of ruby wasn't showing up because it was at the end of the PATH environmental variable, so I have created a block of code to check and then add if it doesn't find it.
powershell_script "add_chefdk_bin_to_shell" do
code '$oldPath=(Get-ItemProperty -Path \'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment\' -Name PATH).Path
$newPath= \'C:\opscode\chefdk\embedded\bin;\' + $oldPath
Set-ItemProperty -Path \'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment\' -Name PATH –Value $newPath
'
only_if { `powershell $a = $Env:Path; $a -match 'C:\\opscode\\chefdk\\embedded\\bin'` == "False" }
end
Except when berk shelf runs (to publish the chef cookbook to our chef server) it spits out this error:
**E, [2014-10-24T11:33:55.771484 #2916] ERROR -- : Cookbook file recipes/install.rb has a ruby syntax error:
E, [2014-10-24T11:33:55.771484 #2916] ERROR -- : c:/path/to/cookbook/root/recipes/install.rb:25: invalid multibyte char (US-ASCII)
E, [2014-10-24T11:33:55.771484 #2916] ERROR -- : c:/path/to/cookbook/root/recipes/install.rb:23: invalid multibyte char (US-ASCII)
E, [2014-10-24T11:33:55.771484 #2916] ERROR -- : c:/path/to/cookbook/root/recipes/install.rb:23: syntax error, unexpected $end, expecting keyword_end
E, [2014-10-24T11:33:55.771484 #2916] ERROR -- : ...ger\Environment\' -Name PATH –Value $newPath
E, [2014-10-24T11:33:55.771484 #2916] ERROR -- : ... ^
E, [2014-10-24T11:33:55.771484 #2916] ERROR -- : Ridley::Errors::CookbookSyntaxError: Invalid ruby files in cookbook: gg-web-opsboard (1.0.177).**
This is very-much beginning to frustrate me, I'm only doing this in the first place because chefDK isn't being used as the default ruby (which is screwing a bunch of other stuff up).
There is a secondary issue, if I look at the path, I can clearly see C:\opscode\chefdk\embedded\bin at the end, so why does:
powershell $a = $Env:Path; $a -match 'C:\\opscode\\chefdk\\embedded\\bin'
Register as false?
EDIT:
I tried what #acro444 said but I'm still getting errors:
E, [2014-10-24T12:36:15.642147 #1932] ERROR -- : Cookbook file recipes/install.rb has a ruby syntax error:
E, [2014-10-24T12:36:15.642147 #1932] ERROR -- : c:/path/to/cookbook/root/recipes/install.rb:24: Invalid escape character syntax
E, [2014-10-24T12:36:15.642147 #1932] ERROR -- : ...ry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Sess...
E, [2014-10-24T12:36:15.642147 #1932] ERROR -- : ... ^
E, [2014-10-24T12:36:15.642147 #1932] ERROR -- : c:/path/to/cookbook/root/recipes/recipes/install.rb:24: Invalid escape character syntax
E, [2014-10-24T12:36:15.642147 #1932] ERROR -- : ...HINE\System\CurrentControlSet\Control\Session Manager\Enviro...
E, [2014-10-24T12:36:15.642147 #1932] ERROR -- : ... ^
E, [2014-10-24T12:36:15.642147 #1932] ERROR -- : c:/path/to/cookbook/root/recipes/recipes/install.rb:26: Invalid escape character syntax
E, [2014-10-24T12:36:15.642147 #1932] ERROR -- : ...ry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Sess...
E, [2014-10-24T12:36:15.642147 #1932] ERROR -- : ... ^
E, [2014-10-24T12:36:15.642147 #1932] ERROR -- : c:/path/to/cookbook/root/recipes/install.rb:26: Invalid escape character syntax
E, [2014-10-24T12:36:15.642147 #1932] ERROR -- : ...HINE\System\CurrentControlSet\Control\Session Manager\Enviro...
E, [2014-10-24T12:36:15.642147 #1932] ERROR -- : ... ^
E, [2014-10-24T12:36:15.642147 #1932] ERROR -- : c:/path/to/cookbook/root/recipes/install.rb:26: invalid multibyte char (US-ASCII)
E, [2014-10-24T12:36:15.642147 #1932] ERROR -- : c:/path/to/cookbook/root/recipes/install.rb:23: syntax error, unexpected $end, expecting tSTRING_CONTENT or tSTRING_DBEG or tSTRING_DVAR or tSTRING_END
I did the quadruple backslash escapething you did on all the backslashes and that reduced the error to just :
syntax error, unexpected $end, expecting tSTRING_CONTENT or tSTRING_DBEG or tSTRING_DVAR or tSTRING_END
I removed all trailing white space but that didn't fix it, currently my herdoc looks like:
code <<-EOF
$oldPath=(Get-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\\\\System\\\\CurrentControlSet\\\\Control\\\\Session Manager\\\\Environment' -Name PATH).Path
$newPath='C:\\\\opscode\\\\chefdk\\\\embedded\\\\bin;' + $oldPath
Set-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\\\\System\\\\CurrentControlSet\\\\Control\\\\Session Manager\\\\Environment' -Name PATH –Value $newPath
EOF

If you want, you can skip the guard block, and move some of the operation to ruby like this:
ruby_block "chefdk_path_check" do
block do
current_path = ENV['PATH'].split(';')
chefdk_path = 'C:\\opscode\\chefdk\\embedded\\bin'
current_path.delete_if { |path| path == chefdk_path }
new_path = current_path.unshift(chefdk_path)
`Powershell -Command Set-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Control\\Session Manager\\Environment' -Name PATH –Value '#{new_path}'`
end
end
This will check every time, remove any existing entry (if it is in the wrong position in the path), and add the desired entry to the beginning. No duplicates and a lot less escaping to worry about!

Try structuring the block as follows:
powershell_script "add_chefdk_bin_to_shell" do
code <<-EOF
$oldPath=(Get-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH).Path
$newPath='C:\opscode\chefdk\embedded\bin;' + $oldPath
Set-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH –Value $newPath
EOF
only_if { `powershell -command "$Env:Path -match 'C:\\\\opscode\\\\chefdk\\\\embedded\\\\bin'".strip }` == "False"
end
Your only_if guard has a couple of problems. Firstly, powershell itself requires the paths to be escaped - \\, therefore you need to double escape in the ruby command.
Secondly, the condition will never be met because the powershell command also includes the newline character on the end of the string, and you weren't matching for that. Hence add the strip to the end of the command. You can test that using irb:
irb> `powershell -command "$Env:Path -match 'C:\\\\opscode\\\\chefdk\\\\embedded\\\\bin'"`
=> "True\n"
You may even be able to swap out the guard as it's written altogether and use the built in interpreter:
guard_interpreter :powershell_script
not_if "$Env:Path -match 'C:\\\\opscode\\\\chefdk\\\\embedded\\\\bin'"
Have a good read of this link.

Related

How to build ICU4C 70.1 on HP UX platform?

I want to build ICU4C code for HP UX platform .
ICU4C repo -> https://github.com/unicode-org/icu/tree/release-70-1.
HP-UX version that i am using -
HP-UX B.11.31 U ia64 ,
aCC compiler version that i am using -
HP C/aC++ B3910B A.06.29
I tried +std=c++11 and -AA option with aCC like ->
aCC -DU_ATTRIBUTE_DEPRECATED= -D_REENTRANT -D_THREAD_SAFE -DU_HAVE_ELF_H=1 -DU_HAVE_STRTOD_L=0 -I../common +std=c++11 -w +O2 +Ofltacc +check=stack -AA +DD64 -mt -AA -Wc,-ansi_for_scope,on +W740 +W749 +W823 +W4232 -DVXPSP_CCFLAGS -c +Z -o stubdata.o stubdata.cpp
But when i am building stubdata.cpp file from icu stubdata project its giving me error related to unique_ptr as -
"../common/unicode/localpointer.h", line 238: error #2283: qualified name is not allowed explicit LocalPointer(std::unique_ptr<T> &&p)
"../common/unicode/localpointer.h", line 238: error #2018: expected a ")"
explicit LocalPointer(std::unique_ptr<T> &&p)
^
"../common/unicode/localpointer.h", line 239: error #2028: expression must
have a constant value
: LocalPointerBase<T>(p.release()) {}
^
"../common/unicode/localpointer.h", line 238: error #2771: "explicit" is not
allowed
explicit LocalPointer(std::unique_ptr<T> &&p)
^
"../common/unicode/localpointer.h", line 239: error #2065: expected a ";"
: LocalPointerBase<T>(p.release()) {}
^
"../common/unicode/localpointer.h", line 413: error #2283: qualified name is
not allowed
explicit LocalArray(std::unique_ptr<T[]> &&p)
^
"../common/unicode/localpointer.h", line 413: error #2018: expected a ")"
explicit LocalArray(std::unique_ptr<T[]> &&p)
^
"../common/unicode/localpointer.h", line 414: error #2028: expression must
have a constant value
: LocalPointerBase<T>(p.release()) {}
^
"../common/unicode/localpointer.h", line 413: error #2771: "explicit" is not
allowed
explicit LocalArray(std::unique_ptr<T[]> &&p)
^
"../common/unicode/localpointer.h", line 414: error #2065: expected a ";"
: LocalPointerBase<T>(p.release()) {}
^
"../common/unicode/udata.h", line 434: error #2283: qualified name is not
allowed
U_DEFINE_LOCAL_OPEN_POINTER(LocalUDataMemoryPointer, UDataMemory, udata_close);
^
"../common/unicode/udata.h", line 434: error #2018: expected a ")"
U_DEFINE_LOCAL_OPEN_POINTER(LocalUDataMemoryPointer, UDataMemory, udata_close);
^
"../common/unicode/udata.h", line 434: error #2040: expected an identifier
U_DEFINE_LOCAL_OPEN_POINTER(LocalUDataMemoryPointer, UDataMemory, udata_close);
^
"../common/unicode/udata.h", line 434: error #2079: expected a type specifier
U_DEFINE_LOCAL_OPEN_POINTER(LocalUDataMemoryPointer, UDataMemory, udata_close);
^
"../common/unicode/udata.h", line 434: error #2771: "explicit" is not allowed
U_DEFINE_LOCAL_OPEN_POINTER(LocalUDataMemoryPointer, UDataMemory, udata_close);
^
"../common/unicode/udata.h", line 434: error #2065: expected a ";"
U_DEFINE_LOCAL_OPEN_POINTER(LocalUDataMemoryPointer, UDataMemory, udata_close);
^
16 errors detected in the compilation of "stubdata.cpp".
It seems like aCC compiler don't have support for this C++ 11 feature unique_ptr .
Also i tried to run a sample standalone program having unique_ptr , but its not able to compile . Whereas other c++11 features like nullptr / range based for loop etc are compiled with aCC compiler on HP .
Any suggestions?

Executing shell command in groovy throws 'unexpected char' error

I am trying to execute a shell command n groovy
def shellString = "s/\[\|]\|\s\|'\|(\|)//g"
def temp2 = "echo response| sed -e ${shellString}".execute()
It throws compilation error:
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
WorkflowScript: 33: unexpected char: '\' # line 33, column 24.
def shellString = "s/\[\|]\|\s\|'\|(\|)//g"
^
1 error
at org.codehaus.groovy.control.ErrorCollector.failIfErrors(ErrorCollector.java:310)
at org.codehaus.groovy.control.ErrorCollector.addFatalError(ErrorCollector.java:150)
at org.codehaus.groovy.control.ErrorCollector.addError(ErrorCollector.java:120)
at org.codehaus.groovy.control.ErrorCollector.addError(ErrorCollector.java:132)
at org.codehaus.groovy.control.SourceUnit.addError(SourceUnit.java:350)
at org.codehaus.groovy.antlr.AntlrParserPlugin.transformCSTIntoAST(AntlrParserPlugin.java:139)
at org.codehaus.groovy.antlr.AntlrParserPlugin.parseCST(AntlrParserPlugin.java:110)
at org.codehaus.groovy.control.SourceUnit.parse(SourceUnit.java:234)
at org.codehaus.groovy.control.CompilationUnit$1.call(CompilationUnit.java:168)
at org.codehaus.groovy.control.CompilationUnit.applyToSourceUnits(CompilationUnit.java:943)
at org.codehaus.groovy.control.CompilationUnit.doPhaseOperation(CompilationUnit.java:605)
at org.codehaus.groovy.control.CompilationUnit.processPhaseOperations(CompilationUnit.java:581)
at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:558)
at groovy.lang.GroovyClassLoader.doParseClass(GroovyClassLoader.java:298)
at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:268)
at groovy.lang.GroovyShell.parseClass(GroovyShell.java:688)
at groovy.lang.GroovyShell.parse(GroovyShell.java:700)
at org.jenkinsci.plugins.workflow.cps.CpsGroovyShell.doParse(CpsGroovyShell.java:131)
at org.jenkinsci.plugins.workflow.cps.CpsGroovyShell.reparse(CpsGroovyShell.java:125)
at org.jenkinsci.plugins.workflow.cps.CpsFlowExecution.parseScript(CpsFlowExecution.java:560)
at org.jenkinsci.plugins.workflow.cps.CpsFlowExecution.start(CpsFlowExecution.java:521)
at org.jenkinsci.plugins.workflow.job.WorkflowRun.run(WorkflowRun.java:330)
at hudson.model.ResourceController.execute(ResourceController.java:97)
at hudson.model.Executor.run(Executor.java:429)
shellString isn't a slashed string, so not sure why a \ would create a problem. Any help is appreciated.
You need to escape slash to avoid compilation errors:
def shellString = "s/\\[\\|]\\|\\s\\|'\\|(\\|)//g"
def temp2 = "echo response| sed -e ${shellString}".execute()
println temp2.text
Output:
response| sed -e s/\[\|]\|\s\|'\|(\|)//g
This will fail on many levels. The biggest problem you will face is the fact, that execute is really just executing a process (not a shell command). So first of all you can not use | at all. Next quoting arguments will not work, because execute will just split at whitespace. So if you want to use "shellisms" use the equivalent of sh -c "..." instead and use execute on a string array. E.g.
["sh", "-c", "..."].execute()
Then you can put your ... shell code in there with all the redirections, quotings, env-vars etc. with the proper Groovy quoting applied as mentioned in the other answer.
And to circumvent all of that: why even bother with sed here? Just use replaceAll on the resulting string on the groovy side of things.

use Chef file.insert_line_if_no_match method for CIDR address

I am trying to use file.insert_line_if_no_match for CIDR address:
attributes/default.rb:
default["chefclustercidr"]["ip"] = "a.b.c.d/24"
recipe/default.rb
ruby_block "chef-backend.rb" do
block do
file = Chef::Util::FileEdit.new("/etc/chef-backend/chef-backend.rb")
file.insert_line_if_no_match("/publish_address/" , "publish_address i#{node['chefclusterbe1']['ip']}")
file.insert_line_if_no_match("/postgresql/" , "postgresql.md5_auth_cidr_addresses = ["samehost", "samenet", "#{node['chefclustercidr']['ip']}/24"]")
file.write_file
end
end
but getting ruby syntax error
$ruby -c default.rb
default.rb:95: syntax error, unexpected tIDENTIFIER, expecting ')'
th_cidr_addresses = ["samehost", "samenet","#{node['chefclus
^
default.rb:95: syntax error, unexpected tIDENTIFIER, expecting keyword_end
resses = ["samehost", "samenet","#{node['chefclustercidr']['
^
default.rb:99: syntax error, unexpected keyword_end, expecting end-of-input
FileEdit is an internal class and using it from recipe code is NOT SUPPORTED. Do not use it. Period.
That said, the problem is you have unescaped double quotes in your string.
Instead of insert_line_if_no_match you can deal with it another way, using bash and grep. I have added the way to another question you can have a look here
here is the bash resource i usually use to append to files only if there is no match:
bash 'append line(s) to file if it doesnt exist' do
user 'user'
code <<-EOS
cat >>/home/file <<EOL
*.* ##172.167.189.67:514
EOL
EOS
not_if "grep -q 172.167.189.67 /home/file"
end
you may need to run cookstyle on that ^

Powershell warning and error handling

The following code I am writing to replace a batch script which I have below.
$Script:srcpath = ((Get-Location).Path)
$Script:configure = "$Script:srcpath\qtbase\configure.bat"
if (Get-Item "$Script:srcpath\qtbase\configure.bat" -WarningAction (Write-Warning "$Script:configure not found. Did you forget to run 'init-repository'?")) {
continue
}
I am try to rewrite the qt configure batch script:
set "srcpath=%~dp0"
set "configure=%srcpath%qtbase\configure.bat"
if not exist "%configure%" (
echo %configure% not found. Did you forget to run "init-repository"? >&2
exit /b 1
)
if not exist qtbase mkdir qtbase || exit /b 1
echo + cd qtbase
cd qtbase || exit /b 1
echo + %configure% -top-level %*
call %configure% -top-level %*
set err=%errorlevel%
cd ..
exit /b %err%
The error I am getting in PowerShell is the following:
Get-Item : Cannot bind parameter 'WarningAction' to the target. Exception setting
"WarningAction": "Object reference not set to an instance of an object."
At line:4 char:67
+ ... rningAction (Write-Warning "$Script:configure not found. Did you forg ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : WriteError: (:) [Get-Item], ParameterBindingException
+ FullyQualifiedErrorId : ParameterBindingFailed,Microsoft.PowerShell.Commands.GetItemCommand
The problem is the error being thrown is erroneous because the warning am calling is what should take its place to tell people that the item doesn't exist. so run "init-repository".
There isn't a good, "if not exist" in PowerShell.
Okay, there is, but it looks like this:
catch [System.Management.Automation.ItemNotFoundException]
which I am having problems with getting to work.
Why am I doing this before someone asks is because I feel that Microsoft will phase out CMD some time it's good to have updated scripts.
Why it's not working
WarningAction does not work like that.
From the about_CommonParameters documentation:
Determines how the cmdlet responds to a warning from the command. "Continue" is the default value. This parameter works only when the command generates a warning message. For example, this parameter works when a command contains the Write-Warning cmdlet.
So, essentially, the value of WarningAction is Continue by default and can be set to Inquire, SilentlyContinue or Stop. The value it is set to determine what action is taken if the Get-item command throws a warning, not what warning to write if Get-item throws a warning.
You can change the preference variable $WarningPreference to set the WarningAction within the current scope, or precede by a scope modifier.
How to make it work
Test-Path
I second Richard's comment to use Test-Path. This will return True or False, depending on whether it finds the file.
if (-not (Test-Path -Path "$Script:srcpath\qtbase\configure.bat")){
Write-Warning 'Does not exist!'
# do other stuff
continue
}else{
Get-Item $configure
}
try/catch
You could try to catch the exception thrown by Get-Item directly in a try/catch. In a similar way to WarningAction, there is ErrorAction which determines what to do if an error is thrown. Terminating error is required, so ErrorAction is set to Stop.
try{
Get-Item $configure -ErrorAction Stop
}catch [System.Management.Automation.ItemNotFoundException]{
Write-Output "Item not found"
# do other stuff
}catch{
Write-Output "Some other error"
$Error[0] # prints last error
}

passing parameters from a windows batch script into a powershell script

I have a powershell script which uses 'quser' command to extract data regarding users logged onto a series of terminal servers.
I want to add a timestamp to the output files, this timestamp variable is created in a windows batch file which then calls the powershell script passes the computername and timestamp, but the powershell script is erroring with 'Missing ')' in function parameter list'
param(
[CmdletBinding()]
[Parameter(ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true)]
[string[]]$ComputerName = 'localhost'
[string[]]$timestamp <========= this is the line I have added
)
If I remove my added line (marked in the code above), the script runs fine
You need to add a comma between the parameters:
param(
[CmdletBinding()]
[Parameter(ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true)]
[string[]]$ComputerName = 'localhost',
[string[]]$timestamp
)
Also unless you want multiple timestamps you probably just want it to be a string rather than a string array (so [string]$timestamp).
The error message I get looks like this (except that it is in red). The first error points at the end of the localhost line then there is a knock-on error for what by that time seems to be a spurious ):
PS C:\> param(
>> [CmdletBinding()]
>> [Parameter(ValueFromPipeline=$true,
>> ValueFromPipelineByPropertyName=$true)]
>> [string[]]$ComputerName = 'localhost'
>> [string[]]$timestamp
>> )
>>
At line:5 char:38
+ [string[]]$ComputerName = 'localhost'
+ ~
Missing ')' in function parameter list.
At line:7 char:1
+ )
+ ~
Unexpected token ')' in expression or statement.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : MissingEndParenthesisInFunctionParameterList
I'm using Powershell 3 here. Other versions may show the error differently.

Resources