I have Cascade choice parameter 'mount_name' which is to form its value from referencing two other parameters. I tried -
choice(name: "project_name", choices: ["xxx", "null", "yyy"], description: "choose the appropriate project"),
choice(name: "environment", choices: ["dev", "qa", "pre-prod", "prod"], description: "choose the appropriate environment"),
[$class: 'CascadeChoiceParameter',
name: 'mount_name_name', choiceType: 'PT_SINGLE_SELECT', description: 'Choose the appropriate name',
filterLength: 1, filterable: false, referencedParameters: 'environment',
script: [$class: 'GroovyScript',
script: [
classpath: [],
sandbox: true,
script: """
if (environment == 'prod' || environment == 'pre-prod') {
return["efs-${params.project_name.replace('-','')}-prod"]
} else if (environment == 'dev') {
return["efs-${params.project_name.replace('-','')}-dev"]
} else {
return["efs-${params.project_name.replace('-','')}"]
}
""".stripIndent()
]
]
],
Expected result : environment = 'prod' , project_name='b2b-srv' then mount_name = 'efs-b2bsrv-prod'
Current result : environment = 'prod' , project_name='b2b-srv' then mount_name = nothing
Related
Trying to set multiple values in CascadeChoiceParameter's for referencedParameters. What the format should be? Docs documentation said that it should be 'string', but in case of setting referencedParameters: 'param1,param2' it goes to fallback script.
here is the class:
[$class: 'CascadeChoiceParameter',
name: 'SOME_PARAM',
description: 'some description',
randomName: '',
script: [$class: 'GroovyScript',
fallbackScript: [
classpath: [],
sandbox: true,
script: 'return ["item_1"]'
],
script: [
classpath: [],
sandbox: true,
script: """
if(PARAM_2.equals("some_value") && PARAM_3.equals("some_value")) {
return ["item_1", "item_2", "item_3"]
} else if((PARAM_2.equals("E2E_Tests") || (PARAM_2.equals("Real_API")) && PARAM_3.equals("knox_guard")) {
return ["item_1", "item_2", "item_4"]
} else {
return ["item_1"]
}
""".stripIndent()
]
],
choiceType: 'PT_SINGLE_SELECT',
referencedParameters: 'PARAM_2,PARAM_3',
filterable: false,
filterLength: 1
],
The fallback script is used if/when there is any kind of exception/error when attempting to execute the main script. In your case, there is a compilation error in the else if((PARAM_2.equals("E2E_Tests") || (PARAM_2.equals("Real_API")) && PARAM_3.equals("knox_guard")) line. All the open parenthesis haven't been closed - there are 6 open parenthesis and only 5 close parenthesis. Anyway, I haven't tested a CascadeChoiceParameter version of the pipeline. I have tested using activeChoiceReactiveParam. Below is a working job DSL:
String choicesScript = """
if(PARAM_2.equals("some_value") && PARAM_3.equals("some_value")) {
return ["item_1", "item_2", "item_3"]
} else if((PARAM_2.equals("E2E_Tests") || (PARAM_2.equals("Real_API")) && PARAM_3.equals("knox_guard"))) {
return ["item_1", "item_2", "item_4"]
} else {
return ["item_5"]
}
""".stripIndent()
String pipeline = '''
pipeline {
agent any
stages {
stage('Show parameter values') {
steps {
echo "PARAM_2: ${params.PARAM_2}, PARAM_3: ${params.PARAM_3}, SOME_PARAM: ${params.SOME_PARAM}"
}
}
}
}
'''.stripIndent()
pipelineJob('reactive-params') {
parameters {
activeChoiceParam('PARAM_2') {
description('First test parameter')
choiceType('SINGLE_SELECT')
groovyScript {
script('return ["some_value", "E2E_Tests", "Real_API"]')
}
}
activeChoiceParam('PARAM_3') {
description('Second test parameter')
choiceType('SINGLE_SELECT')
groovyScript {
script('return ["some_value", "knox_guard"]')
}
}
activeChoiceReactiveParam('SOME_PARAM') {
description('some description')
choiceType('SINGLE_SELECT')
referencedParameter('PARAM_2')
referencedParameter('PARAM_3')
groovyScript {
script(choicesScript)
fallbackScript('return ["item_1"]')
}
}
}
definition {
cps {
script(pipeline)
}
}
}
I'm into the terraform world recently and learning based on the requirements. I've a question on printing the values with a given condition
json file:
{
"team1" : [
{
"engg_name" : "Alex",
"guid" : 1001,
"scope" : "QA"
},
{
"engg_name" : "Trex",
"guid" : 1002,
"scope" : "QA"
},
{
"engg_name" : "Jessica",
"guid" : 1003,
"scope" : "QA"
},
{
"engg_name" : "Tom",
"guid" : 1004,
"scope" : "DEV"
}
],
"team2" : [
{
"engg_name" : "Roger",
"guid" : 2001,
"scope" : "DEV"
},
{
"engg_name" : "Jhonny",
"guid" : 2002,
"scope" : "DEV"
}
]
}
What I'm trying:
print the engg whose scope is DEV from the json file
locals {
teams = jsondecode(file("${path.module}/teams_info.json"))
engg_with_scope_dev = flatten([for i in local.teams : i.teams if keys(local.teams).scope == "DEV"])
}
Error:
engg_with_scope_dev = flatten([for i in local.teams : i.teams if keys(local.teams).scope == "DEV"])
|----------------
| local.teams is object with 2 attributes
This value does not have any attributes.
Can someone suggest me what's the right way to just print based on the condition?
output must be as following:
engg_with_scope_dev = ["Tom", "Roger", "Jhonny"]
You need an embedded for loop for this:
locals {
teams = jsondecode(file("${path.module}/teams_info.json"))
engg_with_scope_dev = flatten([for team in local.teams : [
for engineer in team : engineer.engg_name if engineer.scope == "DEV"
]])
}
Other solution would be to use a concatenation of the lists with ellipsis operator:
locals {
teams = jsondecode(file("${path.module}/teams_info.json"))
engg_with_scope_dev = ([
for engineer in concat(values(local.teams)...) : engineer.engg_name if engineer.scope == "DEV"
])
}
But also, a simple flatten with values would work as well:
locals {
teams = jsondecode(file("${path.module}/teams_info.json"))
engg_with_scope_dev = ([
for engineer in flatten(values(local.teams)) : engineer.engg_name if engineer.scope == "DEV"
])
}
I am trying to run nested for loop on terraform.
I have the following Yaml file:
Employees:
- Department:
- Dev:
- name: "danielf"
role: developer
details:
email : danielf#example.com
firstname : daniel
lastname : folsik
- name: "johnb"
role: developer
details:
email : johnb#example.com
firstname : john
lastname : belk
- Ops:
- name: "benol"
role: devops
details:
email : benol#example.com
firstname : ben
lastname : olkin
- name: "pauld"
role: devops
details:
email : pauld#example.com
firstname : paul
lastname : dempler
I am using locals to get the yaml data:
locals {
ou_config = yamldecode(file("employees.yaml"))
}
I want to run into the list of objects on "Dev" and "Ops" lists using for_each.
for example, I want to run on the "Dev" list to get the following list of objects in the first iteration:
[
{
key = "email"
value = "danielf#example.com"
},
{
key = "firstname"
value = "daniel"
},
{
key = "lastname"
value = "folskin"
}
]
The next run on the for_each will be:
[
{
key = "email"
value = "johnb#example.com"
},
{
key = "firstname"
value = "john"
},
{
key = "lastname"
value = "belk"
}
]
etc.
How can I do it on terraform?
If I understand correctly, all you are trying to extract is the details portion of that yaml file ...
Here is what I would do to get all:
locals {
ou_config = yamldecode(file("employees.yaml"))
expanded_names = flatten([
for e in local.ou_config.Employees : [
for d in e.Department : [
for key, person in d : [
for key, value in person : [
value.details
]
]
]
]
])
}
output "test" {
value = local.expanded_names
}
And if we want to filter we add an if key == "Dev"
locals {
ou_config = yamldecode(file("employees.yaml"))
expanded_names = flatten([
for e in local.ou_config.Employees : [
for d in e.Department : [
for key, person in d : [
for key, value in person : [
value.details
]
] if key == "Dev"
]
]
])
}
output "test" {
value = local.expanded_names
}
A terraform plan on that will look like:
Changes to Outputs:
+ test = [
+ {
+ email = "danielf#example.com"
+ firstname = "daniel"
+ lastname = "folsik"
},
+ {
+ email = "johnb#example.com"
+ firstname = "john"
+ lastname = "belk"
},
]
That format should be easier to loop in the final resource than the key value you suggested
I have an item where multiple attributes may need to be updated (but not always), and each of them requires a different set of conditions. In the below example, I would like to do the following:
Set a new JobTitle if it has changed, and the LastUpdated value is more recent
Append a Project ID to the ProjectsList list and Project to Projects if a new Project ID listed.
Is it possible to run all of these updates within a single update_item expression, or is it necessary to use transactions?
Example item:
{
'PK': 'PERSON#123456789',
'SK': 'PERSON#123456789',
'ID': '123456789',
'Name': 'Bob Smith',
'Birthday': '01/01/2000',
'Street': '65 LEXINGTON AVE',
'Zip': '12345',
'City': 'NEW YORK',
'State': 'NY',
'JobTitle': 'Project Manager',
'LastUpdated': '20210101',
'Projects': [
{
'Name': 'Project A',
'ID': '987654321'
},
{
'Name': 'Project B',
'ID': '756394733'
},
],
"ProjectList": ['987654321', '756394733']
}
Each separate update expressions (via a Table resource):
# Update job title if changed
r = table.update_item(
Key = {
"PK": data['PK'],
"SK": data['SK']
},
UpdateExpression = "SET #JobTitle = :JobTitle",
ExpressionAttributeNames = {
"#JobTitle": "JobTitle",
"#LastUpdated": "LastUpdated"
},
ExpressionAttributeValues = {
":JobTitle": "Senior Project Manager",
":LastUpdated": '20210102'
},
ConditionExpression = "#LastUpdated < :LastUpdated AND #JobTitle <> :JobTitle"
)
# Update projects if not in list
r = table.update_item(
Key = {
"PK": data['PK'],
"SK": data['SK']
},
UpdateExpression = """
SET #Projects = list_append(if_not_exists(#Projects, :empty_list), :ProjectMap),
#ProjectList = list_append(if_not_exists(#ProjectList, :empty_list), :ProjectID)
""",
ConditionExpression = "not(contains(#ProjectList, :ProjectID))",
ExpressionAttributeNames = {
"#Projects": "Projects",
"#ProjectList": "ProjectList"
},
ExpressionAttributeValues = {
":empty_list": [],
":ProjectMap": [{
"Name": "Project C"
"ID": "7463848373"
}],
":ProjectID": ["7463848373"]
}
)
What I want to do
# (1) Update job title if changed or (2) update projects if not in list
r = table.update_item(
Key = {
"PK": data['PK'],
"SK": data['SK']
},
UpdateExpression = """
SET
#JobTitle = :JobTitle,
#Projects = list_append(if_not_exists(#Projects, :empty_list), :ProjectMap),
#ProjectList = list_append(if_not_exists(#ProjectList, :empty_list), :ProjectID)
""",
ExpressionAttributeNames = {
"#JobTitle": "JobTitle",
"#LastUpdated": "LastUpdated",
"#Projects": "Projects",
"#ProjectList": "ProjectList"
},
ExpressionAttributeValues = {
":empty_list": [],
":JobTitle": "Senior Project Manager",
":LastUpdated": '20210102'
":ProjectMap": [{
"Name": "Project C"
"ID": "7463848373"
}],
":ProjectID": ["7463848373"]
},
ConditionExpression = "(#LastUpdated < :LastUpdated AND #JobTitle <> :JobTitle) OR not(contains(#ProjectList, :ProjectID))"
)
I'm skeptical that this is possible due to this line in the AWS documentation:
For these data manipulation operations, you can specify a condition expression to determine which items should be modified. If the condition expression evaluates to true, the operation succeeds; otherwise, the operation fails.
Using groovy, how can I substitute the value of an array in another array variable?
For eg.:
def Env = [
'Env1',
'Env2',
'Env3'
]
def Job = [
[
name: "Job1",
label: "<$Env>",
action: #!/usr/bin/bash
blah
blah
],
[
name: "Job2",
label: "<$Env>",
action: #!/usr/bin/bash
blah
blah
]
]
I want the label field in the second array Job to be populated by every item in Env
If the code isn't dynamic you can just do:
def Env = ['Env1','Env2', 'Env3']
def Job = [
[
name: "Job1",
label: "<${Env[0]}>",
action: '#!/usr/bin/bash'
],
[
name: "Job2",
label: "<${Env[1]}>",
action: '#!/usr/bin/bash'
]
]
If it's dynamic you can do:
Job.eachWithIndex{ obj, idx ->
obj.label = Env[idx]
}