I have a script like this:
param(
[Alias('a')]
[string]$aval,
[Alias('b')]
[switch]$bval,
[Alias('c')]
[string]$cval
)
if($aval.length -gt 1)
{
Do-Something
}
elseif($bval)
{
Do-Something-Else
}
elseif($cval.length -gt 1)
{
Do-Another-Thing
}
else
{
Do-This
}
If someone calls my script like so, an ugly error is displayed saying it is missing an argument for parameter 'aval/bval/cval':
PS C:\> .\MyScript.ps1 -a
C:\MyScript.ps1 : Missing an argument for parameter 'aval'. Specify a
parameter of type 'System.String' and try again.
At line:1 char:18
+ .\MyScript.ps1 -n <<<<
+ CategoryInfo : InvalidArgument: (:) [MyScript.ps1], ParameterBindingException
+ FullyQualifiedErrorId : MissingArgument,MyScript.ps1
Is there any way to make a cleaner, possibly one line, error appear instead? Also, is there a better way to handle parameters then a list of elseif statements (my actual script has ~10 parameters)?
The script sometimes passes an argument with a parameter as well:
EX:
PS C:\> .\MyScript.ps1 -b ServerName
Thanks for any help!
There are a few things that you can look at here. First, if the parameter will never have an associated value and you just want to know if the script was called with the parameter or not, then use a [switch] parameter instead of a string.
Here is a very simple example of using a switch parameter:
param(
[switch]$a
)
if($a){
'Switch was present'
}else{
'No switch present'
}
Save that as a script and run it with and without the -a parameter.
If you will sometimes have the parameter present with some value being passed in but other times without the value, then give the parameter a default value when you define it:
[Alias('a')]
[string]$aval = '',
Then in your logic if something was passed in, the length of the string will be gt 1.
As for the if-then structure that you have, there are a plethora of options for handling this sort of logic. with the little bit of information that you have shared, I suspect that using switch structure will be the best plan:
Get-Help about_Switch
Related
I'm trying to write a Jenkins plugin that provides Step myStep which expects a block with a single parameter per below
myStep { someParameter -> <user code> }
I've found that BodyInvoker ( retrieved from StepContext.newBodyInvoker() ) provides no facilities to invoke the user provided block with parameters.
Expanding the environment would not be ideal, even though the type of the parameter is serializable ( to/from String ), i'd have to provide additional helpers to carry out this serialization, e.g
myStep { deserialize "${env.value}" <user code> }
do i have any other option to pass a non-string type in to the provided block? would type information of the parameter survive even if i did?
nb: i understand you can return a value from your Execution.run() which will be the return value of the step in the pipeline. It's just that in a related shared pipeline library i'm already heavily leaning in to this pattern of:
withFoo { computedFoo ->
# something with computedFoo
withBar computedFoo { computedBar ->
}
}
i prefer this over
computedFoo = withFoo
# something with computedFoo
withBar(computedFoo)
..then again, i couldn't find any plugins pulling this off.
no matter how close i look at workflow-step-api-plugin this doesn't seem possible today. The options are:
expand the environment context with a string value
add a custom object to the context ( requires access to step context in pipeline )
use a return value
I need to accept all kinds of global Jenkins variables as strings (basically as parameters to ansible like system - a template stored in \vars).
def proof = "\"${params.REPOSITORY_NAME}\""
echo proof
def before = "\"\${params.REPOSITORY_NAME}\""
echo before
def after = Eval.me(before)
echo after
The result is:
[Pipeline] echo
"asfd"
[Pipeline] echo
"${params.REPOSITORY_NAME}"
groovy.lang.MissingPropertyException: No such property: params for class: Script1
the first echo proves that the param value actually exists.
the second echo is the what the input actually looks like.
the third echo should have emitted asdf instead I get the exception.
Any ideas? I'm hours into this :-(
You may want to check:
groovy: Have a field name, need to set value and don't want to use switch
1st Variant
In case you have: xyz="REPOSITORY_NAME" and want the value of the parameter REPOSITORY_NAME you can simply use:
def xyz = "REPOSITORY_NAME"
echo params."$xyz" // will print the value of params.REPOSITORY_NAME
In case if your variable xyz must hold the full string including params. you could use the following solution
#NonCPS
def split(string) {
string.split(/\./)
}
def xyz = "params.REPOSITORY_NAME"
def splitString = split(xyz)
echo this."${splitString[0]}"."${splitString[1]}" // will print the value of params.REPOSITORY_NAME
2nd Variant
In case you want to specify an environment variable name as parameter you can use:
env.“${params.REPOSITORY_NAME}”
In plain groovy env[params.REPOSITORY_NAME] would work but in pipeline this one would not work inside the sandbox.
That way you first retrieve the value of REPOSITORY_NAME and than use it as key to a environment variable.
Using directly env.REPOSITORY_NAME will not be the same as it would try to use REPOSITORY_NAME itself as the key.
E.g. say you have a job named MyJob with the following script:
assert(params.MyParameter == "JOB_NAME")
echo env."${params.MyParameter}"
assert(env."${params.MyParameter}" == 'MyJob')
This will print the name of the job (MyJob) to the console assuming you did set the MyParameter parameter to JOB_NAME. Both asserts will pass.
Please don’t forget to open a node{} block first in case you want to retrieve the environment of that very node.
After trying all those solutions, found out that this works for my problem (which sounds VERY similar to the question asked - not exactly sure though):
${env[REPOSITORY_NAME]}
what is wrong with below code, comparing 2 strings in groovy
I am trying do the comparison between the 2 parameters in a single line to make it look tidier
if (params.dirname == ((params.path =~ ~/${params.dirname}/).with { matches() ? it[0] : null })) {
print success
}
Throwing Exception -
java.lang.NoSuchMethodError: No such DSL method 'matches' found among steps
There is no need to over-complicate your use case. According to:
params.dirname = hde, params.path = /usr/tmp/jenkins/hde/filename.txt or /usr/hde/jenkins/ing/filename.txt or any random path which has hde in it
you are trying to find if given string a contains substring b. It can be done using Java's method String.contains(String substring). Alternatively you can use regular expression for that, but String.contains() just looks a few times simpler to understand what is your intention. Consider following Groovy script:
def params = [
dirname: 'hde',
path: '/usr/tmp/jenkins/hde/filename.txt'
]
// Using String.contains()
if (params.path.contains(params.dirname)) {
println "Path '${params.path}' contains '${params.dirname}'"
}
// Using regular expression
if (params.path ==~ /(.*)${params.dirname}(.*)/) {
println "Path '${params.path}' contains '${params.dirname}'"
}
When you run it both if statements evaluates to true:
Path '/usr/tmp/jenkins/hde/filename.txt' contains 'hde'
Path '/usr/tmp/jenkins/hde/filename.txt' contains 'hde'
I want my Powershell script to be able to handle two parameter sets as shown below.
Set 1:
Param1: GroupName via pipe
Param2: FilePath
Called like: "GROUPNAME" | script.ps1 FilePath
Set 2:
Param1: GroupName
Param2: FilePath
Called like: script.ps1 GroupName FilePath
In both cases both arguments are mandatory.
I have tried everything I can think of and the closest I think I have gotten is this:
[CmdletBinding(DefaultParameterSetName="Pipe")]
param (
[Parameter(Mandatory=$true,Position=0,ValueFromPipeline=$false,HelpMessage="AD Group Name",ParameterSetName="Param")]
[Parameter(Mandatory=$true,ValueFromPipeline=$true,HelpMessage="AD Group Name",ParameterSetName="Pipe")]
[ValidateNotNullOrEmpty()]
[String]$GroupName,
[Parameter(Mandatory=$true,Position=1,ValueFromPipeline=$false,HelpMessage="Path to CSV",ParameterSetName="Param")]
[Parameter(Mandatory=$true,Position=0,ValueFromPipeline=$false,HelpMessage="Path to CSV",ParameterSetName="Pipe")]
[ValidateNotNullOrEmpty()]
[String]$FilePath
)
This does not work, as it always expect the second argument at position 1; any ideas?
You don't need two parameter sets. ValueFromPipeline=$true makes the function accept input from the pipeline, but doesn't require that it come from the pipeline - it can be specified as an argument just as well.
I came across a groovy syntax that creates a link in gsp file like this:
class LoginTagLib {
def loginControl = {
out << """[${link(action:"login",controller:"user"){"Login"}}]"""
}}
I know that it will eventually turned into this in html:
Login
However, there are 2 portion of the syntax that I don't understand:
I don't understand ${link(action:"login",controller:"user"){"Login"}}:
I get the $(), which is used for string interpolation.
I get the link(action:"login",controller:"user") too, just 2 arguments passed into link
but what is the {"Login"} doing behind?
I don't understand the """[ ]""" that is used to enclose the whole thing, I tried to take away a pair of ", but it wounldn't work anymore. So it proves to me it has it's significance.
Anybody help to shed some light?
Thanks
In groovy if the last argument of a function is a closure you can you change this syntax foo(arg1, arg2, ..., { ... }) to foo(arg1, arg2, ...) { ... }. this is what happens here, the last argument of link() is a closure that should evaluate to the textual representation of the link
''' and ''' allow for multi-line string. """ """ are the same but also support variable substitution