I'm trying to create an Ansible task to save the content of a variable to a new file.
Using Ansible 2.5.13 and Python 2.7.5.
I've tried already to copy the content of the variable to a destination path where the file should be created...
- name: Save alert rule example file to Prometheus
copy:
content: "{{ alert_rule_config }}"
dest: /opt/compose/prom/alert_rule.yml
Tried also to create the file before copying the content of the variable
- name: Create alert rule file
file:
path: /opt/compose/prom/alert_rule.yml
state: touch
- name: Save alert rule example file to Prometheus
copy:
content: "{{ alert_rule_config }}"
dest: /opt/compose/prom/alert_rule.yml
Tried to wrap the destination path in quotes...
But no matter what a directory /opt/compose/prom/alert_rule.yml/ is created!
The content of the variable is something like
alert_rule_config:
groups:
- name: debug-metrics
rules:
- alert: DebugAlert
expr: test_expression
I expect the file to be created (because it does not exist) and the content of the variable to be saved to the newly created file but the task fails with
FAILED! => {"changed": false, "msg": "can not use content with a dir as dest"}
I want to avoid issuing a command and would prefer to use an Ansible module.
You need to create the target directory instead of the target file, or you will get Destination directory /opt/compose/prom does not exist in the first option or Error, could not touch target: [Errno 2] No such file or directory: '/opt/compose/prom/alert_rule.yml' in the second option.
- name: Create alert rule containing directory
file:
path: /opt/compose/prom/
state: directory
- name: Save alert rule example file to Prometheus
copy:
content: "{{ alert_rule_config }}"
dest: /opt/compose/prom/alert_rule.yml
But as #Calum Halpin says, if during your tests you did an error and created a directory /opt/compose/prom/alert_rule.yml/, you need to remove it before.
This will happen if a directory /opt/compose/prom/alert_rule.yml already exists when your tasks are run.
To remove it as part of your tasks add
- file:
path: /opt/compose/prom/alert_rule.yml
state: absent
ahead of your other tasks.
Related
Can I create temp file with a fixed name with the tempfile module?
- name: Create temporary file
tempfile:
state: file
suffix: 2023-2-2
prefix: app_010
register: tempfile_1
delegate_to: localhost
- name: debug
debug:
msg: "{{ tempfile_1.path }}"
The result is
ok: [localhost] => {
"msg": "/tmp/app_010zvhvpiqr2023-2-2"
}
tempfile creates a random file name, but, I would like to give it a hardcoded name.
I want to read the temporary file from another playbook, so, should I use regex to find a file that starts with app_010 and finishes with 2023-2-2?
The entire point of tempfile is to create unpredictable temporary files with a random component, because using a predictable name in a world-writable directory like /tmp has security implications.
If you want a predictable, hardcoded name, just use the file module.
I'm trying to create a file on the target server using Ansible.
I would like to get the path from the env variable on the target server.
The code is:
- name: Create a file
win_file:
path: ansible_env.CONFIG_HOME\conf\xyz.txt
state: file
The error I'm receiving is:
"changed": false,
"msg": "path ansible_env.CONFIG_HOME\conf\xyz.txt will not be created"
There are two issues here.
Firstly, since you are trying to use an environment variable, you need braces {{ }} to interpolate the value.
Secondly, have a close read of the docs for win_file where it talks about the way state behaves:
If file, the file will NOT be created if it does not exist
If touch, an empty file will be created if the path does not exist
Taking into consideration the above, the following should work for you:
- name: Create a file
win_file:
path: "{{ ansible_env.CONFIG_HOME }}\conf\xyz.txt"
state: touch
I am working on ansible-playbook, granted I am kind of new at this. Anyways, in the ansible playbook, I modified a file and when I rerun the playbook, I don’t want that file to be modified again.
- name: Check if the domain config.xml has been edited
stat: path={{ domainshome }}/{{ domain_name }}/config/config.xml
register: config
- name: Config.xml modified
debug: msg="The Config.xml has been modified"
when: config.changed
- name: Edit the config.xml - remove extra file-store bad tag
shell: "sed -i '776,780d' {{ domainshome }}/{{ domain_name }}/config/config.xml"
when: config.changed
When I run for the first time, it skips this step.
I need this step to run once and skip if the playbook is rerun.
I am trying to write ansible-playbook and remove entries from config file only when it’s executed for the first time so that it can run the jvm.
Q: "Remove entries from config file only when it’s executed for the first time."
A: It's possible to use the creates parameter of the shell module to make sure the configuration file has been edited only once. For example
- name: Edit the config.xml - remove extra file-store bad tag
shell: "sed -i '776,780d' {{ domainshome }}/{{ domain_name }}/config/config.xml"
args:
creates: "{{ domainshome }}/{{ domain_name }}/config/config.xml.lock"
- name: Create lock file
file:
state: touch
path: "{{ domainshome }}/{{ domain_name }}/config/config.xml.lock"
Notes
Quoting: creates: A filename, when it already exists, this step will not be run.
Fit the path and name of the lock file to your needs
stat module returns information about a file only and never changes a file. The registered variable register: config in this task would never report a file has been changed.
file module and state: touch is not idempotent. Quoting: an existing file or directory will receive updated file access and modification times (similar to the way touch works from the command line).
A better solution would be to modify the command and create the lock file along with sed. For example "sed -i ... && touch /path-to-lockfile/lockfile".
I want to ovrwrite file on remote location using Ansible. No matter content in zip file is changes or not, everytime I run playbook file needs to be overwrite on destination server.
Below is my playbook
- hosts: localhost
tasks:
- name: Checking if File is exsists to copy to update servers.
stat:
path: "/var/lib/abc.zip"
get_checksum: False
get_md5: False
register: win_stat_result
- debug:
var: win_stat_result.stat.exists
- hosts: uploads
tasks:
- name: Getting VARs
debug:
var: hostvars['localhost']['win_stat_result']['stat'] ['exists']
- name: copy Files to Destination Servers
win_copy:
src: "/var/lib/abc.zip"
dest: E:\xyz\data\charts.zip
force: yes
when: hostvars['localhost']['win_stat_result']['stat']['exists']
When I run this playbook it didn't overwrite file on destination as file is already exists. I used force=yes but it didn't worked.
Try the Ansible copy module.
The copy module defaults to overwriting an existing file that is set to the dest parameter (i.e. force defaults to yes). The source file can either come from the remote server you're connected to or the local machine your playbook runs from. Here's a code snippet:
- name: Overwrite file if it exists, the remote server has the source file bc remote_src is set below
copy:
src: "/var/lib/abc.zip"
dest: E:\xyz\data\charts.zip
remote_src: yes
You can remove the file before copy the new one:
- name: Delete file before copy
win_file:
path: E:\xyz\data\charts.zip
state: absent
I've been setting the destination path of every temporary files I have to download. For instance:
- name: Downloading file
uri:
url: "{{url}}"
dest: ~/.ansible/tmp/
Is there any way of reading the configuration variable local_tmp (and remote_tmp) from within the playbook?
I'm not sure why you'd want to place the temporary files under local_tmp/remote_tmp directories handled by Ansible.
There is a module called tempfile which allows you to create a temporary directory under the path specified in system temporary directory:
- name: Ensure a temporary directory for download exists
tempfile:
state: directory
suffix: my_download
register: temp_dir
- name: Ensure a file is downloaded from {{ url }}
uri:
url: "{{ url }}"
dest: "{{ temp_dir.path }}"
and if you want to persist the name across the playbook runs, just create a subdirectory in lookup('env', 'TMPDIR') | default('/tmp') for local, or ansible_env.TMPDIR | default('/tmp') for remote.