I have multiple tasks depend from the value of variable1. I want to check if the value is in {{ variable1 }} but I get an error:
- name: do something when the value in variable1
command: <command>
when: "'value' in {{ variable1 }}"
I'm using ansible 2.0.2
If variable1 is a string, and you are searching for a substring in it, this should work:
when: '"value" in variable1'
if variable1 is an array or dict instead, in will search for the exact string as one of its items.
None of the above answers worked for me in ansible 2.3.0.0, but the following does:
when: variable1 | search("value")
In ansible 2.9 this is deprecated in favor of using ~ concatenation for variable replacement:
when: "variable1.find('v=' ~ value) == -1"
http://jinja.pocoo.org/docs/dev/templates/#other-operators
Other options:
when: "inventory_hostname in groups[sync_source]"
From Ansible 2.5
when: variable1 is search("value")
For negative scenarios
when: not variable1 is search("value")
Some of the answers no longer work as explained.
Currently here is something that works for me in ansible 2.6.x
when: register_var.stdout is search('some_string')
This works for me in Ansible 2.9:
variable1 = www.example.com.
variable2 = www.example.org.
when: ".com" in variable1
and for not:
when: not ".com" in variable2
This example uses regex_search to perform a substring search.
- name: make conditional variable
command: "file -s /dev/xvdf"
register: fsm_out
- name: makefs
command: touch "/tmp/condition_satisfied"
when: fsm_out.stdout | regex_search(' data')
ansible version: 2.4.3.0
In Ansible version 2.9.2:
If your variable variable1 is declared:
when: "'value' in variable1"
If you registered variable1 then:
when: "'value' in variable1.stdout"
use this
when: "{{ 'value' in variable1}}"
instead of
when: "'value' in {{variable1}}"
Also for string comparison you can use
when: "{{ variable1 == 'value' }}"
I used
failed_when: not(promtool_version.stdout.find('1.5.2') != -1)
means - failed only when the previously registered variable "promtool_version" doesn't contains string '1.5.2'.
Related
How to check a null variable in Gitlab pipeline when it's declared with a content of another null variable? Like the variable VAR_NULL below when NO_VAR is null:
variables:
VAR_EMPTY: ""
VAR_NULL: "${NO_VAR}"
Check the pipeline result out where only VAR_EMPTY == "" and NO_VAR == null evaluate to true all others are false.
Pipeline result (a screenshot for convenience, the full result: https://gitlab.com/labaz/test-gitlab-pipeline-null-var/-/pipelines/493036820):
Full pipeline script (https://gitlab.com/labaz/test-gitlab-pipeline-null-var/-/blob/main/.gitlab-ci.yml):
variables:
VAR_EMPTY: ""
VAR_NULL: "${NO_VAR}"
jobTest-Var_Empty-IsNull: # This job runs in the build stage, which runs first.
rules:
- if: '$VAR_EMPTY == null'
script:
- 'echo "VAR_EMPTY IS null"'
jobTest-Var_Empty-IsEmpty: # This job runs in the build stage, which runs first.
rules:
- if: '$VAR_EMPTY == ""'
script:
- 'echo "VAR_EMPTY IS \"\""'
jobTest-Var_Null-IsNull: # This job runs in the build stage, which runs first.
rules:
- if: '$VAR_NULL == null'
script:
- 'echo "VAR_NULL IS null"'
jobTest-Var_Null-IsEmpty: # This job runs in the build stage, which runs first.
rules:
- if: '$VAR_NULL == ""'
script:
- 'echo "VAR_NULL IS Empty"'
jobTest-No_Var-IsNull: # This job runs in the build stage, which runs first.
rules:
- if: '$NO_VAR == null'
script:
- 'echo "NO_VAR IS null"'
jobTest_No_Var-IsEmpty: # This job runs in the build stage, which runs first.
rules:
- if: '$NO_VAR == ""'
script:
- 'echo "NO_VAR IS Empty"'
The problem you're encountering is that VAR_NULL: "${NO_VAR}" is not a null variable. It's actually the same thing as VAR_EMPTY: "" -- you are declaring the variable (therefore it is not null) with an empty value.
The only way to test if the variable was created with another empty variable is to test the original variable itself. That is, test NO_VAR, not VAR_NULL.
An alternative strategy would be to use rules:variables: in order to conditionally declare VAR_NULL
workflow:
rules:
- if: '$NO_VAR' # or '$NO_VAR != null' depending on what you want
variables:
VAR_NULL: "$NO_VAR"
- when: always
jobTest-Var_Null-IsNull:
rules:
- if: '$VAR_NULL == null'
script:
- echo "VAR_NULL is null"
As soon as any "if" is matched the job runs.
there's no overriding it with a later "never"
also 'if when never' - who thought that was a good idea?
Anyhow to make the if less matchy ... you can use parentheses.
rules:
- if: ($CI_COMMIT_BRANCH && $SOME_VAR == null)
However this doesn't work:
- if: ('$CI_COMMIT_BRANCH == develop' && $SOME_VAR == null)
not sure why considering this is valid...
- if: '$CI_COMMIT_BRANCH == develop'
essentially I want to skip some jobs when 'some_var' is set (which happens when I run a manual pipeline)
So putting it all together ...
And before your eyes glaze over "workflow" and its "rules" are a separate beast from "job_name:" "rules:"
ostensibly workflow needs "always or never" and the rules can control when jobs run.. but only if you put a "never" .. unless i'm missing something... )
workflow:
rules:
- if: '$SOMEVAR == null'
variables:
BLOCK_JOB: "False"
- when: always
#then in my job we can do something like:
rules:
- if: ($CI_COMMIT_BRANCH == "develop" && $BLOCK_JOB)
yes all of that because this doesn't work
- if: ('$CI_COMMIT_BRANCH == develop' && $SOME_VAR == null)
so now I can have a job that runs on develop unless its run manually (which is when I set SOMEVAR)
and then its skipped.
Workflow also seems to just randomly refuse to do somethings...
for example this Doesn't work ( trying to set a var based on project name) never evals as true so CI_PATH_TYPE remains unset... but imo looking at it with my wetware... it should...
rules:
- if: $CI_PROJECT_NAME == "some-project-name"
variables:
CI_PATH_TYPE: project
But this does? because.. null is magic..?
rules:
- if: '$somevar == null'
variables:
BLOCK_JOB: "False"
also any time something is quoted in various ways in these examples gitlab ci made me do it exactly like that, any other variations and it shits the bed.
so once again the latest tool is just more black magic, hot take: gitlab-ci is bad.
I want to run a gitlab job in every case EXCEPT the variable RUN is defined and contains the value run3.
So again:
variable RUN is undefined: run the job
variable RUN is defined and does not contain the value run3: run the job
variable RUN is defined and does contain the value run3: DO NOT run the job
I tried the following rules:
rules:
- if: $RUN != null && $RUN == "run3"
when: never
rules:
- if: $RUN != "" && $RUN == "run3"
when: never
rules:
- if: $RUN == "run3"
when: never
Without the variable RUN being defined, no job was run. I expected the job to have been run.
How to fix it? Where is the problem in the logic?
After some time-consuming try-and-error trials I found the solution: As you cannot test if a variable exists, you have to create the rule the other way around. It means, you run the job if the value does not match:
The correct rule is then:
- if: $RUN != "run3"
when: always
- when: never
The first part only evaluates to true if the variable exists AND if the variable does not evaluate to run3. In that case the job is run.
The second part then tells to NOT run the job in any other case.
You're close
rules:
- if: $RUN == "run3"
when: never
This is correct, but you also need a default - when:
To emulate the default behavior of no rules when the first rule does not match, set the default as on_success
rules:
- if: $RUN == "run3"
when: never # don't run the job in this case
- when: on_success # run per usual in all other cases
Alex, maybe you can try:
if: $RUN != undefined && $RUN == "run3"
when: never
I have a .yaml file
variables:
- name: command1
value: none
- scripts: |
echo '##vso[task.setvariable variable=command1]new_value'
- ${{ if ne(variables['command1'], 'none') }}:
- template: templates/run.yml#temp1 # Template reference
parameters:
COMMAND: '$(command1)'
I have created the variable for two reason ,
to be global
I dont want it to be displayed in the variable list for the users
I want the template only to be executed if variable value of 'command1' is not 'none'
Currently it is not skipping , it keeps executing it even if the value inside the variable is not none.
The other if conditions format I have used is
- ${{ if ne(variables['taskName.command1'], 'none') }}:
- ${{ if ne('$(command1)', 'none') }}:
None of the above worked
Please help in resolving this issue.
As it is written here:
The difference between runtime and compile time expression syntaxes is primarily what context is available. In a compile-time expression (${{ }}), you have access to parameters and statically defined variables. In a runtime expression ($[ ]), you have access to more variables but no parameters.
variables:
staticVar: 'my value' # static variable
compileVar: ${{ variables.staticVar }} # compile time expression
isMain: $[eq(variables['Build.SourceBranch'], 'refs/heads/main')] # runtime expression
steps:
- script: |
echo ${{variables.staticVar}} # outputs my value
echo $(compileVar) # outputs my value
echo $(isMain) # outputs True
So it could work for your YAML value:
variables:
- name: command1
value: none
steps:
- scripts: |
echo '##vso[task.setvariable variable=command1]new_value'
- ${{ if ne(variables.command1, 'none') }}:
- template: templates/run.yml#temp1 # Template reference
parameters:
COMMAND: '$(command1)'
However, it will pick this value:
variables:
- name: command1
value: none
There is no chance that it will take this:
- scripts: |
echo '##vso[task.setvariable variable=command1]new_value'
It is because ${{}} expressions are compile time and echo '##vso[task.setvariable variable=command1]new_value' is runtime.
I want to hard code 2 different values based on variable stdout in a single play.If a service is running then i want to hard code value as good else bad.How to use this logic in ansible?
I can able to hard code one value based on status result.
---
- hosts: localhost
connection: local
gather_facts: false
vars:
tasks:
- name: load var from file
include_vars:
file: /tmp/var.json
name: imported_var
- name: Checking mysqld status
shell: service mysqld status
register: mysqld_stat
- name: Checking mysqld status
shell: service httpd status
register: httpd_stat
- name: append more key/values
set_fact:
imported_var: "{{ imported_var| default([]) | combine({ 'mysqld_status': 'good' })}}"
when: mysqld_stat.rc == 0
- name: append more key/values
set_fact:
imported_var: "{{ imported_var| default([]) | combine({ 'httpd_status': 'good' })}}"
when: httpd_stat.rc == 0
- name: write var to file
copy:
content: "{{ imported_var | to_nice_json }}"
dest: /tmp/final.json
I want to hard code mysqld_status : Good if mysqld_stat.rc == 0 or mysqld-status: Bad if mysqld_stat.rc != 0.Is it possible to achieve in single play.(i.e) in single command
There are many of ways of approaching this problem. You could just add a second set_fact that runs when mysqld_stat.rc != 0. In the following example, only one of the two set_fact tasks will run:
- name: append more key/values
set_fact:
imported_var: "{{ imported_var| default({}) | combine({ 'mysqld_status': 'good' })}}"
when: mysqld_stat.rc == 0
- name: append more key/values
set_fact:
imported_var: "{{ imported_var| default({}) | combine({ 'mysqld_status': 'bad' })}}"
when: mysqld_stat.rc != 0
You could instead use Ansible's ternary filter:
- name: append more key/values
set_fact:
imported_var: "{{ imported_var| default({}) | combine({ 'mysqld_status': (mysqld_stat.rc == 0)|ternary('good', 'bad') })}}"
How do I use the when statement based on the standard output of register: result? If standard output exists I want somecommand to run if no standard output exists I want someothercommand to run.
- hosts: myhosts
tasks:
- name: echo hello
command: echo hello
register: result
- command: somecommand {{ result.stdout }}
when: result|success
- command: someothercommand
when: result|failed
Try checking to see it if equals a blank string or not?
- hosts: myhosts
tasks:
- name: echo hello
command: echo hello
register: result
- command: somecommand {{ result.stdout }}
when: result.stdout != ""
- command: someothercommand
when: result.stdout == ""
As of 2018, the recommended way to test if output is empty is just:
when: result.stdout | length > 0
That is the pythonic way of evaluating truth, null, empty strings, empty lists all evaluate as false.
Other older alternatives not recommended or even not working:
result.stdout != "" would not pass ansible-lint check!
result.stdout | bool will NOT work as most strings will evaluate as False, only cases where it would return true is if stdout happens to be one of the true, yes,... kind of strings.
result.stdout used to work but now triggers:
[DEPRECATION WARNING]: evaluating as a bare variable, this
behaviour will go away and you might need to add |bool to the
expression in the future. Also see CONDITIONAL_BARE_VARS configuration
toggle.. This feature will be removed in version 2.12. Deprecation
warnings can be disabled by setting deprecation_warnings=False in
ansible.cfg.`
To expand on this answer and address the comment regarding potential problems if stdout isn't defined, the following when statement can be used to ensure stdout is defined before trying to check its length:
when: result.stdout is defined and result.stdout | length > 0